[题解]POJ 3683 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).
The next N lines contain the Si, Ti and Di. Si and Ti are in the format of hh:mm.
【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
---------------------------------------------------------------------------------------------------------------------------------
【题目大意】
有n场婚礼,每场婚礼有对应的开始和结束时间,每场婚礼都需要举行一场仪式,仪式持续时间为Di。仪式可以在婚礼前举行[Si,Si+Di],或者在婚礼后举行[Ti-Di,Ti]。要求每个婚礼的仪式不冲突,求一组仪式时间安排的可行解。
【题解】
裸的2-SAT问题。主要是建图,注意判断哪些方案会出现矛盾。其它为2-SAT的基础代码。
1 #include<iostream>
2 #include<cstdio>
3 #include<cstring>
4 #include<string>
5 using namespace std;
6 #define MAXN 1020*2
7 int n;
8 struct Thing
9 {
10 int st,ed,Len;
11 }p[MAXN];
12 struct node
13 {
14 int v;
15 node *next;
16 };
17 node edge[MAXN*MAXN];
18 node *cnt=&edge[0];
19 node *adj[MAXN];
20 node edge2[MAXN*MAXN];
21 node *cnt2=&edge2[0];
22 node *adj2[MAXN];
23 int dfn[MAXN],low[MAXN],dcnt;
24 int Belong[MAXN],Num[MAXN];
25 int stack[MAXN],top;
26 int In[MAXN],opp[MAXN],scc;
27 int q[MAXN],col[MAXN];
28 bool Instack[MAXN],ans[MAXN];
29 char s1[10],s2[10];
30 inline void Addedge(int u,int v)
31 {
32 node *p=++cnt;
33 p->v=v;
34 p->next=adj[u];
35 adj[u]=p;
36 }
37 inline void Addedge2(int u,int v)
38 {
39 node *p=++cnt2;
40 p->v=v;
41 p->next=adj2[u];
42 adj2[u]=p;
43 }
44 inline int Cal(char str[])
45 {
46 int Ret=((str[0]-'0')*10+str[1]-'0')*60+(str[3]-'0')*10+str[4]-'0';
47 return Ret;
48 }
49 inline bool Check(int st1,int len1,int st2,int len2)
50 {
51 return (st2<st1+len1)&&(st1<st2+len2);
52 }
53 void Read()
54 {
55 //scanf("%d",&n);
56 int i;
57 for(i=1;i<=n;i++)
58 {
59 scanf("%s%s%d",s1,s2,&p[i].Len);
60 p[i].st=Cal(s1);
61 p[i].ed=Cal(s2);
62 }
63 }
64 void Build_map()
65 {
66 int i,j;
67 for(i=1;i<=n;i++)
68 for(j=1;j<=n;j++)
69 {
70 if(i==j)
71 continue;
72 if(Check(p[i].st,p[i].Len,p[j].st,p[j].Len))
73 Addedge(i,j+n);
74 if(Check(p[i].st,p[i].Len,p[j].ed-p[j].Len,p[j].Len))
75 Addedge(i,j);
76 if(Check(p[i].ed-p[i].Len,p[i].Len,p[j].st,p[j].Len))
77 Addedge(i+n,j+n);
78 if(Check(p[i].ed-p[i].Len,p[i].Len,p[j].ed-p[j].Len,p[j].Len))
79 Addedge(i+n,j);
80 }
81 }
82 void Tarjan(int u)
83 {
84 int v;
85 dfn[u]=low[u]=++dcnt;
86 stack[++top]=u;
87 Instack[u]=true;
88 for(node *p=adj[u];p;p=p->next)
89 {
90 v=p->v;
91 if(!dfn[v])
92 {
93 Tarjan(v);
94 low[u]=min(low[u],low[v]);
95 }
96 else if(Instack[v])
97 low[u]=min(low[u],dfn[v]);
98 }
99 if(dfn[u]==low[u])
100 {
101 scc++;
102 do
103 {
104 v=stack[top];
105 top--;
106 Instack[v]=false;
107 Belong[v]=scc;
108 Num[scc]++;
109 }while(v!=u);
110 }
111 }
112 bool Work()
113 {
114 int i;
115 for(i=1;i<=n*2;i++)
116 if(!dfn[i])
117 Tarjan(i);
118 for(i=1;i<=n;i++)
119 {
120 if(Belong[i]==Belong[i+n])
121 return false;
122 opp[Belong[i]]=Belong[i+n];
123 opp[Belong[i+n]]=Belong[i];
124 }
125 int u,v;
126 for(i=1;i<=n*2;i++)
127 for(node *p=adj[i];p;p=p->next)
128 {
129 v=p->v;
130 if(Belong[i]!=Belong[v])
131 {
132 Addedge2(Belong[v],Belong[i]);
133 In[Belong[i]]++;
134 }
135 }
136 int l=0,r=0;
137 for(i=1;i<=scc;i++)
138 if(!In[i])
139 {
140 q[r]=i;
141 r++;
142 }
143 while(l<r)
144 {
145 u=q[l];
146 l++;
147 if(!col[u])
148 {
149 col[u]=1;
150 col[opp[u]]=-1;
151 }
152 for(node *p=adj2[u];p;p=p->next)
153 {
154 v=p->v;
155 In[v]--;
156 if(!In[v])
157 {
158 q[r]=v;
159 r++;
160 }
161 }
162 }
163 for(i=1;i<=n;i++)
164 if(col[Belong[i]]==1)
165 ans[i]=true;
166 return true;
167 }
168 void Print()
169 {
170 if(Work())
171 {
172 printf("YES\n");
173 int i;
174 for(i=1;i<=n;i++)
175 {
176 if(ans[i])
177 printf("%02d:%02d %02d:%02d\n",p[i].st/60,p[i].st%60,(p[i].st+p[i].Len)/60,(p[i].st+p[i].Len)%60);
178 else
179 printf("%02d:%02d %02d:%02d\n",(p[i].ed-p[i].Len)/60,(p[i].ed-p[i].Len)%60,p[i].ed/60,p[i].ed%60);
180 }
181 }
182 else
183 printf("NO\n");
184 }
185 inline void Pre()
186 {
187 memset(edge,0,sizeof(edge));
188 memset(adj,0,sizeof(adj));
189 cnt=&edge[0];
190 memset(edge2,0,sizeof(edge2));
191 memset(adj2,0,sizeof(adj2));
192 cnt2=&edge2[0];
193 memset(dfn,0,sizeof(dfn));
194 memset(low,0,sizeof(low));
195 dcnt=0;
196 top=0;
197 memset(Instack,false,sizeof(Instack));
198 memset(Belong,0,sizeof(Belong));
199 memset(Num,0,sizeof(Num));
200 scc=0;
201 memset(opp,0,sizeof(opp));
202 memset(In,0,sizeof(In));
203 memset(q,0,sizeof(q));
204 memset(col,0,sizeof(col));
205 memset(ans,false,sizeof(ans));
206 }
207 int main()
208 {
209 //freopen("Data.in","r",stdin);
210 //freopen("Data.out","w",stdout);
211 while(scanf("%d",&n)!=EOF)
212 {
213 Pre();
214 Read();
215 Build_map();
216 Print();
217 }
218 return 0;
219 }