题意:有n个婚礼,每个婚礼有起始时间si,结束时间ti,还有一个主持时间ti,ti必须安排在婚礼的开始或者结束,主持由祭祀来做,但是只有一个祭祀,所以各个婚礼的主持时间不能重复,问你有没有可能正常的安排主持时间,不能输出no,能的话要输出具体的答案:即每个婚礼的主持时间段是什么样的。
分析:把一个婚礼分成两个点,分别代表开始时间和结束时间。那么就把问题转换成了一个2-SAT问题。若两个点之间有冲突(也就是时间有重合)则连边。然后就是裸的2-SAT输出问题了。
把数组开大后就一次AC的感觉真是太好了。亏我之前那段旧代码调了那么久还是不知道那里出问题。看来把代码写的优美真的是很重要的啊(自夸ing)。
代码:
var n,e,d,tot,sum:longint; x,y,z,belong,last,stack,state,dfn,low,du,color,con:array[1..3000] of longint; f:array[1..3000] of boolean; side:array[1..2000000] of record x,y,next:longint; end; function check(a,b,c,d:longint):boolean; begin if (b<=c)or(d<=a) then exit(false); exit(true); end; procedure add(x,y:longint); begin inc(e); side[e].x:=x; side[e].y:=y; side[e].next:=last[x]; last[x]:=e; end; function min(x,y:longint):longint; begin if x<y then exit(x) else exit(y); end; procedure init; var i,j,t1,t2:longint; c:char; s:string; begin readln(n); for i:=1 to n do begin read(c);s:=c;read(c);s:=s+c;val(s,t1); read(c); read(c);s:=c;read(c);s:=s+c;val(s,t2); x[i]:=t1*60+t2; read(c); read(c);s:=c;read(c);s:=s+c;val(s,t1); read(c); read(c);s:=c;read(c);s:=s+c;val(s,t2); y[i]:=t1*60+t2; readln(z[i]); end; for i:=1 to n-1 do for j:=i+1 to n do begin if check(x[i],x[i]+z[i],x[j],x[j]+z[j]) then begin add(i,j+n); add(j,i+n); end; if check(x[i],x[i]+z[i],y[j]-z[j],y[j]) then begin add(i,j); add(j+n,i+n); end; if check(y[i]-z[i],y[i],x[j],x[j]+z[j]) then begin add(i+n,j+n); add(j,i); end; if check(y[i]-z[i],y[i],y[j]-z[j],y[j]) then begin add(i+n,j); add(j+n,i); end; end; end; procedure dfs(x:longint); var i:longint; begin inc(d); dfn[x]:=d; low[x]:=d; inc(tot); stack[tot]:=x; f[x]:=true; i:=last[x]; while i>0 do with side[i] do begin if dfn[y]=0 then begin dfs(y); low[x]:=min(low[x],low[y]); end else if f[y] then low[x]:=min(low[x],dfn[y]); i:=next; end; if dfn[x]=low[x] then begin inc(sum); repeat i:=stack[tot]; dec(tot); f[i]:=false; belong[i]:=sum; until i=x; end; end; procedure tarjan; var i:longint; begin fillchar(f,sizeof(f),false); for i:=1 to n*2 do if dfn[i]=0 then dfs(i); end; procedure topsort; var head,tail,i:longint; begin head:=0; tail:=0; for i:=1 to sum do if du[i]=0 then begin inc(tail); state[tail]:=i; end; repeat inc(head); i:=last[state[head]]; while i>0 do with side[i] do begin dec(du[y]); if du[y]=0 then begin inc(tail); state[tail]:=y; end; i:=next; end; until head>=tail; end; procedure dfs_blue(x:longint); var i:longint; begin color[x]:=-1; i:=last[x]; while i>0 do with side[i] do begin if color[y]=0 then dfs_blue(y); i:=next; end; end; procedure dfs_red; var i:longint; begin for i:=1 to sum do if color[state[i]]=0 then begin color[state[i]]:=1; dfs_blue(con[state[i]]); end; end; procedure print; var i,t1,t2:longint; begin writeln('YES'); for i:=1 to n do begin if color[belong[i]]=1 then begin t1:=x[i]; t2:=x[i]+z[i]; end else begin t1:=y[i]-z[i]; t2:=y[i]; end; if t1 div 60<10 then write(0); write(t1 div 60,':'); if t1 mod 60<10 then write(0); write(t1 mod 60,' '); if t2 div 60<10 then write(0); write(t2 div 60,':'); if t2 mod 60<10 then write(0); writeln(t2 mod 60); end; end; procedure work; var i:longint; begin for i:=1 to n do begin if belong[i]=belong[i+n] then begin writeln('NO'); exit; end; con[belong[i]]:=belong[i+n]; con[belong[i+n]]:=belong[i]; end; fillchar(last,sizeof(last),0); for i:=1 to e do with side[i] do if belong[x]<>belong[y] then begin add(belong[y],belong[x]); inc(du[belong[x]]); end; topsort; dfs_red; print; end; begin init; tarjan; work; end.