poj3683 Priest John's Busiest Day 2011-12-26
Priest John's Busiest DayTime Limit: 2000MSMemory Limit: 65536KTotal Submissions: 5263Accepted: 1828Special Judge
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
208:00 09:00 3008:15 09:00 20
Sample Output
YES08:00 08:3008:40 09:00
Source
POJ Founder Monthly Contest – 2008.08.31, Dagger and Facer __________________________________________
1 Program Stone; 2 var n,le,deep,lt,i,j:longint; 3 si,ti:array[1..1000]of longint; 4 d:array[1..1000]of longint; 5 map:array[1..2000,1..2000]of boolean; 6 fs,fv:array[1..2000]of boolean; 7 head,dfn,low,tr,rd,stack:array[1..2000]of longint; 8 next,date:array[1..4000000]of longint; 9 function judge(asi,ati,bsi,bti:longint):boolean; //判断两个时间段是否冲突 10 begin 11 if ((asi<bsi)and(bsi<ati))or((asi<bti)and(bti<ati)) 12 or((bsi<asi)and(asi<bti))or((bsi<ati)and(ati<bti)) 13 or((asi=bsi)and(ati=bti)) then judge:=true 14 else judge:=false; 15 end; 16 Procedure add(x,y:longint); 17 begin 18 inc(le); 19 date[le]:=y; 20 next[le]:=head[x]; 21 head[x]:=le; 22 end; 23 procedure init; //读入和建边 24 var i,j,k:longint; 25 c,c1,c2,c3,c4,sp:char; 26 begin 27 readln(n); 28 for i:=1 to n do 29 begin 30 read(c1,c2,c,c3,c4,sp); 31 j:=(ord(c1)-48)*10+ord(c2)-48; 32 k:=(ord(c3)-48)*10+ord(c4)-48; 33 si[i]:=j*60+k; 34 read(c1,c2,c,c3,c4); 35 j:=(ord(c1)-48)*10+ord(c2)-48; 36 k:=(ord(c3)-48)*10+ord(c4)-48; 37 ti[i]:=j*60+k; 38 readln(d[i]); 39 for j:=1 to i-1 do 40 begin 41 if judge(si[i],si[i]+d[i],si[j],si[j]+d[j]) then begin 42 add(i,j+n); 43 add(j,i+n); 44 end; 45 if judge(si[i],si[i]+d[i],ti[j]-d[j],ti[j]) then begin 46 add(i,j); 47 add(j+n,i+n); 48 end; 49 if judge(ti[i]-d[i],ti[i],ti[j]-d[j],ti[j]) then begin 50 add(i+n,j); 51 add(j+n,i); 52 end; 53 if judge(ti[i]-d[i],ti[i],si[j],si[j]+d[j]) then begin 54 add(i+n,j+n); 55 add(j,i); 56 end; 57 end; 58 end; 59 end; 60 61 Procedure work(x:longint); 62 var i:longint; 63 begin 64 inc(lt); 65 repeat 66 tr[stack[le]]:=lt; 67 if stack[le]>n then i:=stack[le]-n else i:=stack[le]+n; 68 if tr[i]=lt then begin 69 writeln('NO'); 70 halt; 71 end; 72 fs[stack[le]]:=false; 73 dec(le); 74 until stack[le+1]=x; 75 end; 76 77 function min(a,b:longint):longint; 78 begin 79 if a<b then min:=a else min:=b; 80 end; 81 82 Procedure tarjan(x:longint); 83 var i,j,k:longint; 84 begin 85 fv[x]:=false; 86 inc(deep); 87 dfn[x]:=deep; 88 low[x]:=deep; 89 inc(le); 90 stack[le]:=x; 91 fs[x]:=true; 92 i:=head[x]; 93 while i<>0 do 94 begin 95 if fv[date[i]] then begin 96 tarjan(date[i]); 97 low[x]:=min(low[x],low[date[i]]); 98 end 99 else if fs[date[i]] then low[x]:=min(low[x],dfn[date[i]]); 100 i:=next[i]; 101 end; 102 if dfn[x]=low[x] then work(x); 103 end; 104 105 procedure built; //染色后重新建图 106 var i,j,k:longint; 107 begin 108 for k:=1 to 2*n do 109 begin 110 i:=head[k]; 111 while i<>0 do 112 begin 113 if (map[tr[k],tr[date[i]]]=false)and(tr[k]<>tr[date[i]]) then 114 begin 115 inc(rd[tr[date[i]]]); //一个点的度 116 map[tr[k],tr[date[i]]]:=true; 117 end; 118 i:=next[i]; 119 end; 120 end; 121 end; 122 Procedure topo; //拓扑排序 123 var i,x:longint; 124 begin 125 le:=0; 126 fillchar(fv,sizeof(fv),true); 127 for i:=1 to lt do 128 begin 129 if rd[i]=0 then begin inc(le);stack[le]:=i;fv[i]:=false;end; 130 end; 131 x:=0; 132 while x<le do 133 begin 134 inc(x); 135 for i:=1 to lt do 136 if (map[stack[x],i])and(fv[i]) then 137 begin 138 dec(rd[i]); 139 if rd[i]=0 then begin inc(le);stack[le]:=i;fv[i]:=false;end; 140 end; 141 end; 142 end; 143 procedure print(x,y:longint); 144 begin 145 if x<10 then write(0); 146 write(x,':'); 147 if y<10 then write(0); 148 write(y,' '); 149 end; 150 Procedure recall(x:longint); 151 var i,j:longint; 152 begin 153 fv[x]:=false; 154 for i:=1 to lt do 155 if (map[i,x])and(i<>x)and(fv[i]) then recall(i); 156 end; 157 Procedure main; 158 var i,j,k,l:longint; 159 begin 160 fillchar(fv,sizeof(fv),true); 161 fillchar(fs,sizeof(fs),false); 162 for i:=le downto 1 do //按拓扑序从后往前取点 163 if fv[stack[i]] then 164 begin 165 fv[stack[i]]:=false; 166 for j:=1 to 2*n do 167 if tr[j]=stack[i] then 168 begin 169 fs[j]:=true; 170 if j>n then begin if fv[tr[j-n]] then recall(tr[j-n]);end //取一个点后应删除与他对立的点以及指向与他对立的点的点 171 else begin if fv[tr[j+n]] then recall(tr[j+n]);end; 172 173 end; 174 end; 175 for j:=1 to n do 176 begin 177 if fs[j] then 178 begin 179 print(si[j] div 60,si[j] mod 60); 180 print((si[j]+d[j])div 60,(si[j]+d[j])mod 60); 181 end; 182 if fs[j+n] then 183 begin 184 print((ti[j]-d[j])div 60,(ti[j]-d[j]) mod 60); 185 print(ti[j] div 60,ti[j] mod 60); 186 end; 187 writeln; 188 end; 189 end; 190 191 Begin 192 init; 193 fillchar(fv,sizeof(fv),true); 194 fillchar(fs,sizeof(fs),false); 195 le:=0; 196 for i:=1 to 2*n do 197 if fv[i] then tarjan(i); 198 writeln('YES'); 199 built; 200 topo; 201 main; 202 end.