题目: | Ikki's Story IV - Panda's Trick | |
来源: | Pku 3207 | |
题目大意: | 一个圆上有N个点,顺时针从0到N-1排列。给出M条线连接两个点,要么在圆外要么 在圆内,判断给出的所有线段是否不规范相交。 Output a line, either “ | |
数据范围: | n ≤ 1,000, m ≤ 500 | |
样例: | 4 2 0 1 3 2 | panda is telling the truth... |
做题思路: | 把每个线段看成两个点,I代表在圆外,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