题目大意
有n个婚礼,每个婚礼有起始时间si,结束时间ti,还有一个主持时间ti,ti必须安排在婚礼的开始或者结束,主持由祭祀来做,但是只有一个祭祀,所以各个婚礼的主持时间不能重复,问你有没有可能正常的安排主持时间,不能输出no,能的话要输出具体的答案:即每个婚礼的主持时间段是什么样的。
分析
把一个婚礼分成两个点,分别代表一场婚礼开头主持和结束主持(用分钟算)的时间。那么就把问题转换成了一个2-SAT问题。若两个点之间有冲突(也就是时间有重合)则连边(具体见程序)。然后就是裸的2-SAT输出问题了(我打了200+的tarjan+拓扑)(要把tarjan的数组设大一些)。
代码
type
arr=record
x,y,next:longint;
end;
var
a,a1:array[1..2000000] of arr;
f:array[0..2000] of boolean;
ls,zan,g,con,b,c,co:array[0..2000] of longint;
dfn,low:array[0..3000] of longint;
x,y,z:array[0..5000] of longint;
tot,sum,n,m:longint;
i,j,k:longint;
e,d:longint;
cc:char;
s:string;
procedure add(x,y:longint);
begin
inc(e);
a[e].x:=x;
a[e].y:=y;
a[e].next:=ls[x];
ls[x]:=e;
end;
function min(x,y:longint):longint;
begin
if x<y then exit(x)
else exit(y);
end;
procedure dfs(x:longint);
var
i:longint;
begin
inc(d);
dfn[x]:=d;
low[x]:=d;
inc(tot);
zan[tot]:=x;
f[x]:=true;
i:=ls[x];
while i>0 do
with a[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 low[x]=dfn[x] then
begin
inc(sum);
repeat
i:=zan[tot];
dec(tot);
f[i]:=false;
g[i]:=sum;
until i=x;
end;
end;
procedure tarjan;
var
i:longint;
begin
fillchar(f,sizeof(f),0);
for i:=1 to n*2 do
if dfn[i]=0
then
dfs(i);
end;
procedure topsort;
var
i,j,k:longint;
head,tail:longint;
begin
head:=0;
tail:=0;
fillchar(b,sizeof(b),0);
for i:=1 to sum do
if c[i]=0 then
begin
tail:=tail+1;
b[tail]:=i;
end;
if tail=0 then exit;
repeat
head:=head+1;
i:=ls[b[head]];
while i<>0 do
with a[i] do
begin
c[y]:=c[y]-1;
if c[y]=0
then
begin
tail:=tail+1;
b[tail]:=y;
end;
i:=next;
end;
until tail=head;
end;
procedure set_b(r:longint);
var
i,j,k:longint;
begin
i:=ls[r];
co[r]:=-1;
while i>0 do
with a[i] do
begin
if co[y]=0
then set_b(y);
i:=next;
end;
end;
procedure set_r;
var
i,j,k:longint;
begin
for i:=1 to sum do
if co[b[i]]=0
then
begin
co[b[i]]:=1;
set_b(con[b[i]]);
end;
end;
procedure print;
var
i,t1,t2:longint;
begin
writeln('YES');
for i:=1 to n do
begin
if co[g[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,j,k:longint;
begin
for i:=1 to n do
begin
if g[i]=g[i+n] then
begin
writeln('NO');
exit;
end;
con[g[i]]:=g[i+n];
con[g[i+n]]:=g[i];
end;
fillchar(ls,sizeof(ls),0);
fillchar(c,sizeof(c),0);
a1:=a;
fillchar(a,sizeof(a),0);
j:=e;
e:=0;
for i:=1 to j do
with a1[i] do
if g[x]<>g[y] then
begin
add(g[y],g[x]);
c[g[x]]:=c[g[x]]+1;
end;
topsort;
set_r;
print;
end;
function check(x,y,x1,y1:longint):boolean;
begin
if (y<=x1) or (y1<=x) then exit(false);
check:=true;
end;
procedure init;
var
i,j,k:longint;
begin
readln(n);
for i:=1 to n do
begin
s:='';
read(cc); s:=cc;
read(cc); s:=s+cc;
val(s,j);
read(cc);
s:='';
read(cc); s:=cc;
read(cc); s:=s+cc;
val(s,k);
x[i]:=j*60+k;
read(cc);
s:='';
read(cc); s:=cc;
read(cc); s:=s+cc;
val(s,j);
read(cc);
s:='';
read(cc); s:=cc;
read(cc); s:=s+cc;
val(s,k);
y[i]:=j*60+k;
read(z[i]);
readln;
end;
end;
begin
init;
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(i+n,j+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;
tarjan;
work;
end.