题目: | Get Luffy Out | |
来源: | Pku 2723 | |
题目大意: | N*2种类型的钥匙,M道门,每道门可以用两种类型之一的钥匙打开,门必须按顺序 打开,问最多可以打开几道门 | |
数据范围: | N (1 <= N <= 210) and M (1 <= M <= 211) | |
样例: | 3 6 0 3 1 2 4 5 0 1 0 2 4 1 4 2 3 5 2 2 0 0 | 4 |
做题思路: | 先把编号进行预处理,每个门上的锁变成编号从小到大。 | |
知识点: | 二分答案、2-sat验证、kosaraju |
type
edge=record
y,next:longint;
end;
//====================================================
var
a1,a2:array[0..6000]of edge;
first1,first2,q1,f,a,t1,t2:array[0..6000]oflongint;
time,tot1,tot2,n,m,mm: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;
//============================================================
procedure init;
var
i,x,y,t:longint;
begin
fillchar(a,sizeof(a),0);
fillchar(t1,sizeof(t1),0);
fillchar(t2,sizeof(t2),0);
fori:=1 to n do
begin
readln(x,y);
a[x]:=2*i-1;{<要是对应编号>}
a[y]:=2*i;
end;
fori:=1 to m do
begin
readln(x,y);
ifx>y then
begin
t:=x;x:=y;y:=t;
end;
t1[i]:=a[x];t2[i]:=a[y];
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);
dfs2(q1[i]);
end;
end;
procedure setup;
var
i,x1,x2,y1,y2:longint;
begin
fillchar(first1,sizeof(first1),0);
fillchar(first2,sizeof(first2),0);
fillchar(a1,sizeof(a1),0);
fillchar(a2,sizeof(a2),0);
tot1:=0;tot2:=0;
fori:=1 to mm do
begin
x1:=t1[i];
y1:=t2[i];
ifodd(x1) then x2:=x1+1 else x2:=x1-1;
ifodd(y1) then y2:=y1+1 else y2:=y1-1;
ifx1<>y1 then
begin
build1(x1,y2);build2(y2,x1);
build1(y1,x2);build2(x2,y1);
end
else
begin
build1(x1,x2);build2(x2,x1);
end;
end;
end;
//=======================================================
function pd(x:longint):boolean;
var
i:longint;
begin
mm:=x;
setup;
kosaraju;
fori:=1 to n do
if(f[2*i]=f[2*i-1]) then
begin
exit(false);
end;
exit(true);
end;
//==========================================================
procedure main;
var
l,r,mid:longint;
begin
l:=1;r:=m;
whilel<r do
begin
mid:=(l+r+1)shr 1;
ifnot pd(mid) then r:=mid-1
else l:=mid;
end;
writeln(l);
end;
begin
readln(n,m);
whilen+m<>0 do
begin
init;
kosaraju;
main;
readln(n,m);
end;
end.
题目来源:
http://poj.org/problem?id=2723