Priest John's Busiest Day
Description John is the only priest in his town. September 1st is the John's busiest day in a year because there is an old legend in the town that the couple who get married on that day will be forever blessed by the God of Love. This year N couples plan to get married on the blessed day. The i-th couple plan to hold their wedding from time Si to time Ti. According to the traditions in the town, there must be a special ceremony on which the couple stand before the priest and accept blessings. The i-th couple need Di minutes to finish this ceremony. Moreover, this ceremony must be either at the beginning or the ending of the wedding (i.e. it must be either from Si to Si + Di, or from Ti - Di to Ti). Could you tell John how to arrange his schedule so that he can present at every special ceremonies of the weddings. Note that John can not be present at two weddings simultaneously. Input The first line contains a integer N ( 1 ≤ N ≤ 1000). Output The first line of output contains "YES" or "NO" indicating whether John can be present at every special ceremony. If it is "YES", output another N lines describing the staring time and finishing time of all the ceremonies. Sample Input 2 08:00 09:00 30 08:15 09:00 20 Sample Output YES 08:00 08:30 08:40 09:00 Source POJ Founder Monthly Contest – 2008.08.31, Dagger and Facer
|
题意:有n对人要结婚,牧师分别去主持每个婚礼中的仪式,给出每对新人的开始和结束时间,还有仪式需要的时间,仪式必须要在开始或结束的时间举办,问是否能给出一种方案,使得牧师可以参加所有仪式。
题解:
2-sat。。。
终于把这道题A了。。。
首先,先把每个婚礼的每一段开始时间标记为i*2,结束时间标记为i*2-1。然后缩点,逆向用强联通分量建图。然后用拓扑排序做一遍,输出即可。
安利一个2-sat讲解:2-sat总结
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define MAXN 2010 4 struct node 5 { 6 int begin,end,next; 7 }edge[2*MAXN*MAXN]; 8 struct NODE 9 { 10 int begin,end,next; 11 }edge1[2*MAXN*MAXN]; 12 int cnt,Head[MAXN],cnt1,Head1[MAXN],n,s1[MAXN],t1[MAXN],LOW[MAXN],DFN[MAXN],STACK[MAXN],color[MAXN],q[MAXN],op[MAXN],belong[MAXN],SCC,Id[MAXN],SIZE,top,N; 13 bool INSTACK[MAXN]; 14 void addedge(int bb,int ee) 15 { 16 edge[++cnt].begin=bb;edge[cnt].end=ee;edge[cnt].next=Head[bb];Head[bb]=cnt; 17 } 18 void addedge1(int bb,int ee) 19 { 20 edge1[++cnt1].begin=bb;edge1[cnt1].end=ee;edge1[cnt1].next=Head1[bb];Head1[bb]=cnt1; 21 } 22 int read() 23 { 24 int s=0,fh=1;char ch=getchar(); 25 while(ch<'0'||ch>'9'){if(ch=='-')fh=-1;ch=getchar();} 26 while(ch>='0'&&ch<='9'){s=s*10+(ch-'0');ch=getchar();} 27 return s*fh; 28 } 29 int Judge(int ii,int jj) 30 { 31 if(s1[jj]>=t1[ii]||s1[ii]>=t1[jj])return 0; 32 return 1; 33 } 34 void Build() 35 { 36 int i,j; 37 memset(Head,-1,sizeof(Head));cnt=1; 38 for(i=1;i<=n;i++) 39 { 40 for(j=i+1;j<=n;j++) 41 { 42 if(Judge(2*i,2*j)==1) 43 { 44 addedge(2*i,2*j-1); 45 addedge(2*j,2*i-1); 46 } 47 if(Judge(2*i,2*j-1)==1) 48 { 49 addedge(2*i,2*j); 50 addedge(2*j-1,2*i-1); 51 } 52 if(Judge(2*i-1,2*j)==1) 53 { 54 addedge(2*i-1,2*j-1); 55 addedge(2*j,2*i); 56 } 57 if(Judge(2*i-1,2*j-1)==1) 58 { 59 addedge(2*i-1,2*j); 60 addedge(2*j-1,2*i); 61 } 62 } 63 } 64 } 65 void Tarjan(int u) 66 { 67 int i,v; 68 LOW[u]=DFN[u]=++SIZE; 69 STACK[top++]=u;INSTACK[u]=true; 70 for(i=Head[u];i!=-1;i=edge[i].next) 71 { 72 v=edge[i].end; 73 if(!DFN[v]) 74 { 75 Tarjan(v); 76 LOW[u]=min(LOW[u],LOW[v]); 77 } 78 else if(INSTACK[v]==true)LOW[u]=min(LOW[u],DFN[v]); 79 } 80 if(LOW[u]==DFN[u]) 81 { 82 SCC++; 83 do 84 { 85 v=STACK[--top]; 86 INSTACK[v]=false; 87 belong[v]=SCC; 88 }while(u!=v); 89 } 90 } 91 void solve() 92 { 93 SIZE=0; 94 for(int i=1;i<=N;i++)if(!DFN[i])Tarjan(i); 95 } 96 void dfs(int u) 97 { 98 if(color[u]!=0)return; 99 color[u]=-1; 100 for(int i=Head1[u];i!=-1;i=edge1[i].next)dfs(edge1[i].end); 101 } 102 void Toposort() 103 { 104 int head=0,tail=0,i,u,v; 105 for(i=1;i<=SCC;i++)if(Id[i]==0)q[++tail]=i; 106 while(head<=tail) 107 { 108 u=q[++head]; 109 if(color[u]!=0)continue;//已经被标记过就不用搜索了. 110 color[u]=1;/*若将color[]标记为,代表被标记为选择(即1).*/dfs(op[u]);/*将和u对立的点标记为选择u的对立点(即-1).*/ 111 for(i=Head1[u];i!=-1;i=edge1[i].next) 112 { 113 v=edge1[i].end; 114 Id[v]--;if(Id[v]==0)q[++tail]=v; 115 } 116 } 117 } 118 void write(int k) 119 { 120 printf("%.2d:",k/60); 121 printf("%.2d",k%60); 122 } 123 int main() 124 { 125 int S1,S2,T1,T2,D,i; 126 n=read(); 127 N=0; 128 for(i=1;i<=n;i++) 129 { 130 S1=read();S2=read();T1=read();T2=read();D=read(); 131 s1[++N]=S1*60+S2;t1[N]=s1[N]+D; 132 t1[++N]=T1*60+T2;s1[N]=t1[N]-D; 133 } 134 Build(); 135 solve(); 136 for(i=1;i<=n;i++)if(belong[2*i-1]==belong[2*i]){printf("NO");return 0;} 137 memset(Head1,-1,sizeof(Head1));cnt1=1; 138 for(i=1;i<=cnt;i++) 139 { 140 if(belong[edge[i].begin]!=belong[edge[i].end]){addedge1(belong[edge[i].end],belong[edge[i].begin]);Id[belong[edge[i].begin]]++;} 141 } 142 memset(color,0,sizeof(color)); 143 for(i=1;i<=n;i++) 144 { 145 op[belong[2*i]]=belong[2*i-1]; 146 op[belong[2*i-1]]=belong[2*i]; 147 } 148 Toposort(); 149 printf("YES"); 150 for(i=1;i<=n;i++) 151 { 152 printf(" "); 153 if(color[belong[i*2]]==1){write(s1[i*2]);printf(" ");write(t1[i*2]);} 154 else {write(s1[i*2-1]);printf(" ");write(t1[i*2-1]);} 155 } 156 fclose(stdin); 157 fclose(stdout); 158 return 0; 159 }