题目大意
平面上,一个圆,圆的边上按顺时针放着n个点。现在要连m条边,比如a,b,那么a到b可以从圆的内部连接,也可以从圆的外部连接。给你的信息中,每个点最多只会连接的一条边。问能不能连接这m条边,使这些边都不相交。
分析
对于每条边s,该边有两种连发,一种是圆内,一种是圆外,根据这两种连发把边分为s和s'。若两条边i和j,它们不能在圆内共存,则它们也不能在圆外共存(自己画一下图就明白了),则有边(i,j'),(i',j),(j,i'),(j',i)。然后就是裸的2-SAT问题了。
代码
type
arr=record
x,y,next:longint;
end;
var
a:array[1..5000000] of arr;
f:array[0..2000] of boolean;
ls,zan,g:array[0..2000] of longint;
dfn,low:array[0..3000] of longint;
x,y:array[0..5000] of longint;
tot,sum,n,m:longint;
i,j,k:longint;
e,d:longint;
z:longint;
procedure add(x,y:longint);
begin
inc(e);
a[e].x:=x;
a[e].y:=y;
a[e].next:=ls[x];
ls[x]:=e;
end;
function min(x,y:longint):longint;
begin
if x<y then exit(x)
else exit(y);
end;
procedure dfs(x:longint);
var
i:longint;
begin
inc(d);
dfn[x]:=d;
low[x]:=d;
inc(tot);
zan[tot]:=x;
f[x]:=true;
i:=ls[x];
while i>0 do
with a[i] do
begin
if dfn[y]=0
then begin
dfs(y);
low[x]:=min(low[x],low[y]);
end
else if f[y] then low[x]:=min(low[x],dfn[y]);
i:=next;
end;
if low[x]=dfn[x] then
begin
inc(sum);
repeat
i:=zan[tot];
dec(tot);
f[i]:=false;
g[i]:=sum;
until i=x;
end;
end;
procedure tarjan;
var
i:longint;
begin
fillchar(f,sizeof(f),0);
for i:=1 to m*2 do
if dfn[i]=0
then
dfs(i);
end;
procedure work;
var
i:longint;
begin
for i:=1 to m do
if g[i]=g[i+m] then
begin
writeln('the evil panda is lying again');
exit;
end;
writeln('panda is telling the truth...');
end;
function check(i,j:longint):boolean;
begin
if (x[j]>x[i]) and (x[j]<y[i]) and ((y[j]<x[i]) or (y[j]>y[i]))
then exit(true);
if (y[j]>x[i]) and (y[j]<y[i]) and ((x[j]<x[i]) or (x[j]>y[i]))
then exit(true);
check:=false;
end;
begin
readln(n,m);
for z:=1 to m do
begin
readln(x[z],y[z]);
if x[z]>y[z]
then
begin
k:=x[z];
x[z]:=y[z];
y[z]:=k;
end;
end;
for i:=1 to m-1 do
for j:=i+1 to m do
if check(i,j)
then
begin
add(i,j+m);
add(i+m,j);
add(j,i+m);
add(j+m,i);
end;
tarjan;
work;
end.