Pku 2723 Get Luffy Out

7 篇文章 0 订阅
6 篇文章 0 订阅

题目:

 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

做题思路:

 先把编号进行预处理,每个门上的锁变成编号从小到大。
 构图:
 1)若X和Y在同一个门上,则X向Y'连一条边,Y向X'连一条边。
 2)若两个X在同一个门上,则X必然会使用,则X'向X连一条边。

知识点:

 二分答案、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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值