Pku 3207 Ikki's Story IV - Panda's Trick

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

题目:

Ikki's Story IV - Panda's Trick

来源:

Pku 3207

题目大意:

 一个圆上有N个点,顺时针从0到N-1排列。给出M条线连接两个点,要么在圆外要么  在圆内,判断给出的所有线段是否不规范相交。

 Output a line, either “panda is telling the truth...” (yes)or “the evil panda  is lying again”(no)

数据范围:

 n ≤ 1,000, m ≤ 500

样例:

 4 2
 0 1
 3 2
panda is telling the truth...
 

做题思路:

 把每个线段看成两个点,I代表在圆外,I'代表在圆外。
 显然,本题要求的就是对于所有I和I'只取一个,问是否可以取完所有M组点。
 所以就变成了一个简单的2-sat验证问题。
 构图,若I和J相交,则I向J'连一条边,J'向I连一条边,I'向J连一条边,J向I'连一条  边。
 注:本题数据很弱,在我敲错的情况下都能过

知识点:

 2-sat验证、kosaraju

type
 edge=record
 y,next:longint;
 end;
//====================================================
var
 a1,a2:array[0..1000010]of edge;
 first1,first2,q1,f,a,b:array[0..2020]oflongint;
 time,tot1,tot2,n,m: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(x,l,r:longint):boolean;
begin
 ifr<l then
  if(r<x)and(l>x) then exit(true);
 ifl<r then
  if(l<x)and(r>x) then exit(true);
 exit(false);
end;
//============================================================
procedure init;
var
 i,x1,x2,y1,y2,j,t:longint;
 ch1,ch2:char;
begin
 readln(n,m);
 tot1:=0;tot2:=0;
 fillchar(first1,sizeof(first1),0);
 fillchar(first2,sizeof(first2),0);
 fori:=1 to m do
 readln(a[i],b[i]);
 fori:=1 to m-1 do
  forj:=i+1 to m do
  begin
    if(pd(a[i],a[j],b[j]))and(pd(b[i],b[j],a[j])) or{<如何判断是否交叉:一个点在这条直线(两点间),另一个点在另一边则交叉>}
      (pd(b[i],a[j],b[j]))and(pd(a[i],b[j],a[j])) then
    begin
     build1(2*i-1,2*j);build2(2*j,2*i-1);{<两两连边>}
     build1(2*j-1,2*i);build2(2*i,2*j-1);
     build1(2*i,2*j-1);build2(2*j-1,2*i);
      build1(2*j,2*i-1);build2(2*i-1,2*j);
    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);
   dfs2(q1[i]);
   end;
end;
//=======================================================
procedure main;
var
 i:longint;
begin
 fori:=1 to 2*m do
  if(odd(i))and(f[2*i]=f[2*i-1]) then
  begin
   writeln('the evil panda is lying again');
   exit;
   end;
 writeln('panda is telling the truth...');
end;
//==========================================================
begin
 init;
 kosaraju;
 main;
end.
题目来源: http://poj.org/problem?id=3207

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值