POJ 3683 Priest John's Busiest Day

来源:互联网 发布:小米笔记本 知乎 编辑:程序博客网 时间:2024/04/27 23:05

题意: John是一个牧师,他们家乡人喜欢挤在一天结婚,而且都要John来主持。每段婚礼都必须有一个仪式,要么在婚礼开始的时候开始,要么正好在婚礼结束的时候结束。告诉你每段婚礼的开始时间和结束时间以及仪式持续时间。问:John能不能正好主持完所以仪式,没有时间冲突,输出每个婚礼无冲突的仪式始末时间。


思路: 2-sat模版题。设婚礼开始时启动仪式为A,反之为A'。如果A与B有冲突,那么连接A——B',以此类推这样建图。然后求强连通分量,判断是否有解,有解的话缩图,然后Topsort一下输出。


代码:

#include<string.h>#include<stdio.h>#include<algorithm>#include<queue>using namespace std;#define N 1010int n;struct couple{int s,t,d;void init(char begin[],char end[],int dur){int h,m;d=dur;sscanf(begin,"%d:%d",&h,&m);s=h*60+m;sscanf(end,"%d:%d",&h,&m);t=h*60+m;}}c[N];struct edge{int id,next;};class graph{private:int eid,p[N<<1];edge e[(N*N)<<3];public:void clear(){eid=0;memset(p,-1,sizeof(p));}void insert(int from,int to){e[eid].id=to;e[eid].next=p[from];p[from]=eid++;}int next(int i){return e[i].next;}int head(int u){return p[u];}int getid(int i){return e[i].id;}}G,newG;class twoSat{private:int top,index,newid,stack[N<<1],instack[N<<1],in[N<<1],other[N<<1],belong[N<<1],dfn[N<<1],low[N<<1],color[N<<1];public:void clear(){top=index=newid=0;memset(stack,0,sizeof(stack));memset(instack,0,sizeof(instack));memset(belong,0,sizeof(belong));memset(dfn,0,sizeof(dfn));memset(low,0,sizeof(low));memset(other,0,sizeof(other));memset(in,0,sizeof(in));memset(color,0,sizeof(color));}bool isvisit(int v){return dfn[v];}bool legal(int x1,int x2,int y1,int y2){return x2<=y1 || y2<=x1;}void makeMap(){for(int i=1;i<=n;i++){for(int j=1;j<=n;j++){if(i==j) continue;if(!legal(c[i].s , c[i].s+c[i].d , c[j].s , c[j].s+c[j].d))G.insert(i,j+n);if(!legal(c[i].s , c[i].s+c[i].d , c[j].t-c[j].d , c[j].t))G.insert(i,j);if(!legal(c[i].t-c[i].d , c[i].t , c[j].s , c[j].s+c[j].d))G.insert(i+n,j+n);if(!legal(c[i].t-c[i].d , c[i].t , c[j].t-c[j].d , c[j].t))G.insert(i+n,j);}}}void Tarjan(int u){int v,t;dfn[u]=low[u]=++index;stack[++top]=u;instack[u]=1;for(int i=G.head(u);i!=-1;i=G.next(i)){v=G.getid(i);if(!dfn[v]){Tarjan(v);low[u]=min(low[u],low[v]);}else if(instack[v]){low[u]=min(low[u],dfn[v]);}}if(dfn[u]==low[u]){newid++;do{t=stack[top--];instack[t]=0;belong[t]=newid;}while(t!=u);}}void contract(){int i,u,v;newG.clear();for(u=1;u<=2*n;u++){for(i=G.head(u);i!=-1;i=G.next(i)){v=G.getid(i);if(belong[u]!=belong[v]){newG.insert(belong[v],belong[u]);in[belong[u]]++;}}}}bool exist(){for(int i=1;i<=n;i++){if(belong[i]==belong[i+n]) return false ; //判断是否有解other[belong[i]]=belong[i+n];other[belong[i+n]]=belong[i];}return true;}void Topsort(){int i,u,v;queue<int> q;for(i=1;i<=newid;i++)if(!in[i]) q.push(i);while(!q.empty()){u=q.front(),q.pop();if(!color[u]){color[u]=1;color[other[u]]=-1;}for(i=newG.head(u);i!=-1;i=newG.next(i)){v=newG.getid(i);if( !(--in[v]) ) q.push(v);}}}void putAnswer(){int h,m;Topsort();for(int i=1;i<=n;i++){if(color[belong[i]]==1){h=c[i].s/60;m=c[i].s%60;printf("%02d:%02d ",h,m);h=(c[i].s+c[i].d)/60;m=(c[i].s+c[i].d)%60;printf("%02d:%02d\n",h,m);}else{h=(c[i].t-c[i].d)/60;m=(c[i].t-c[i].d)%60;printf("%02d:%02d ",h,m);h=c[i].t/60;m=c[i].t%60;printf("%02d:%02d\n",h,m);}}}}TS;void init(){G.clear();TS.clear();}void solve(){int i;TS.makeMap();                //建图for(i=1;i<=2*n;i++)        //求强连通分量if(!TS.isvisit(i))TS.Tarjan(i);if(TS.exist()){                   //判断是否有解TS.contract();         //缩图      puts("YES");TS.putAnswer();    //输出答案}else puts("NO");}int main(){int duration;char begin[20],end[20];while(~scanf("%d",&n)){init();for(int i=1;i<=n;i++){scanf("%s %s %d",begin,end,&duration);c[i].init(begin,end,duration);}solve();}return 0;}





原创粉丝点击