题目: | Priest John's Busiest Day | |
来源: | Pku 3683 | |
题目大意: | 有N个区间(A,B),和一个值C。你可以选择使用(A,A+C)或(B-C,B)中一个区 间,使得所有选择出来的N个区间不相交,求方案。 | |
数据范围: | 1 ≤ N ≤ 1000 | |
样例: | 2 08:00 09:00 30 08:15 09:00 20 | YES 08:00 08:30 08:40 09:00 |
做题思路: | 起初看到区间就茫然了,才发现原来就是其中的两段啊,坑。。 时间表达换分钟,最后再换回来。 设区间(A,B)分为I和I'两个区间。 两个区间怎么确定呢?枚举呗 | |
知识点: | 2-sat、kosaraju、枚举 |
type
edge=record
y,next:longint;
end;
var
a1,a2:array[0..1000010]of edge;
first1,first2,q1,q2,f,a,b,c,col:array[0..2020]oflongint;
time,tot1,tot2,n:longint;
//=========================================================
procedure build1(x,y:longint);
begin
inc(tot1);
a1[tot1].y:=y;
a1[tot1].next:=first1[x];
first1[x]:=tot1;
end;
//==================================================================
procedure build2(x,y:longint);
begin
inc(tot2);
a2[tot2].y:=y;
a2[tot2].next:=first2[x];
first2[x]:=tot2;
end;
//=================================================================
function pd(li,ri,lj,rj:longint):boolean;
begin
if((lj<ri)and(rj>li))or((li<rj)and(ri>lj)) then exit(true);
exit(false);
end;
//============================================================
procedure init;
var
i,x1,x2,y1,y2,j,t:longint;
ch1,ch2:char;
begin
readln(n);
tot1:=0;tot2:=0;
fillchar(first1,sizeof(first1),0);
fillchar(first2,sizeof(first2),0);
fori:=1 to n do{<读入并转成分钟>}
begin
read(ch1,ch2);
a[i]:=(ord(ch1)-ord('0'))*10+(ord(ch2)-ord('0'));
read(ch1,ch1,ch2);
a[i]:=a[i]*60+(ord(ch1)-ord('0'))*10+(ord(ch2)-ord('0'));
read(ch1,ch1,ch2);
b[i]:=(ord(ch1)-ord('0'))*10+(ord(ch2)-ord('0'));
read(ch1,ch1,ch2);
b[i]:=b[i]*60+(ord(ch1)-ord('0'))*10+(ord(ch2)-ord('0'));
read(ch1);readln(c[i]);
end;
fori:=1 to n-1 do{<枚举每个区间与别的区间是否存在交集,存在则不连边>}
forj:=i+1 to n do
begin
x1:=i*2-1;x2:=x1+1;
y1:=j*2-1;y2:=y1+1;
t:=0;
ifpd(a[i],a[i]+c[i],a[j],a[j]+c[j]) then t:=1;
ifpd(a[i],a[i]+c[i],b[j]-c[j],b[j]) then
ift=0 then t:=2
else t:=3;
case t of
1:begin
build1(x1,y2);build1(y1,x2);
build2(y2,x1);build2(x2,y1);
end;
2:begin
build1(x1,y1);build1(y2,x2);
build2(y1,x1);build2(x2,y2);
end;
3:begin
build1(x1,x2);build2(x2,x1);
end;
end;
t:=0;
ifpd(b[i]-c[i],b[i],a[j],a[j]+c[j]) then t:=1;
ifpd(b[i]-c[i],b[i],b[j]-c[j],b[j]) then
ift=0 then t:=2
else t:=3;
case t of
1:begin
build1(x2,y2);build1(y1,x1);
build2(y2,x2);build2(x1,y1);
end;
2:begin
build1(x2,y1);build1(y2,x1);
build2(y1,x2);build2(x1,y2);
end;
3:begin
build1(x2,x1);build2(x1,x2);
end;
end;
end;
end;
//===========================================================
procedure dfs1(x:longint);
var
t:longint;
begin
f[x]:=1;
t:=first1[x];
whilet>0 do
begin
iff[a1[t].y]=0 then dfs1(a1[t].y);
t:=a1[t].next;
end;
inc(time);
q1[time]:=x;
end;
//==========================================================
procedure dfs2(x:longint);
var
t:longint;
begin
f[x]:=time;
t:=first2[x];
whilet>0 do
begin
iff[a2[t].y]=0 then dfs2(a2[t].y);
t:=a2[t].next;
end;
end;
//==============================================================
procedure kosaraju;
var
i:longint;
begin
time:=0;
fillchar(f,sizeof(f),0);
fori:=1 to n*2 do
iff[i]=0 then dfs1(i);
time:=0;
fillchar(f,sizeof(f),0);
fori:=n*2 downto 1 do
iff[q1[i]]=0 then
begin
inc(time);
q2[time]:=q1[i];
dfs2(q1[i]);
end;
end;
//========================================================
procedure delete(x:longint);
var
t:longint;
begin
col[x]:=2;
t:=first2[x];
whilet>0 do
begin
if(col[a2[t].y]=0)and(f[x]=f[a2[t].y]) then delete(a2[t].y);
t:=a2[t].next;
end;
end;
//========================================================
procedure sat(x:longint);
var
t:longint;
begin
col[x]:=1;
t:=first2[x];
whilet>0 do
begin
if(col[a2[t].y]=0)and(f[x]=f[a2[t].y]) then sat(a2[t].y);
t:=a2[t].next;
end;
ifodd(x) then delete(x+1) else delete(x-1);
end;
//=========================================================
procedure print(x,d:longint);{<把分钟转换成小时>}
var
t:longint;
begin
if d=1then
begin
t:=a[x] div 60;
ift<=9 then write(0);
write(t,':');
t:=a[x] mod 60;
ift<=9 then write(0);
write(t,' ');
inc(a[x],c[x]);
t:=a[x] div 60;
ift<=9 then write(0);
write(t,':');
t:=a[x] mod 60;
ift<=9 then write(0);
write(t);
dec(a[x],c[x]);
end
else
begin
dec(b[x],c[x]);
t:=b[x] div 60;
ift<=9 then write(0);
write(t,':');
t:=b[x] mod 60;
ift<=9 then write(0);
write(t,' ');
inc(b[x],c[x]);
t:=b[x] div 60;
ift<=9 then write(0);
write(t,':');
t:=b[x] mod 60;
ift<=9 then write(0);
write(t);
end;
writeln;
end;
//=========================================================
procedure main;
var
i:longint;
begin
fori:=1 to n do
iff[2*i]=f[2*i-1] then
begin
writeln('NO');
exit;
end;
fillchar(col,sizeof(col),0);
fori:=time downto 1 do
ifcol[q2[i]]=0 then sat(q2[i]);
writeln('YES');
fori:=1 to 2*n do
ifcol[i]=1 then
ifodd(i) then print((i+1) shr 1,1) else print((i+1) shr 1,0);
end;
//==========================================================
begin
init;
kosaraju;
main;
end.
题目来源:
http://poj.org/problem?id=3683