题意:平面上,一个圆,圆的边上按顺时针放着n个点。现在要连m条边, 比如a,b,那么a到b可以从圆的内部连接,也可以从圆的外部连接。 给你的信息中,每个点最多只会连接的一条边。问能不能连接这m条边, 使这些边都不相交。
分析:一开始没想到怎么建图,看了别人的题解才想了出来。
对于每条边s,该边有两种连发,一种是圆内,一种是圆外,根据这两种连发把边分为s和s'。
若两条边i和j,它们不能在圆内共存,则它们也不能在圆外共存(自己画一下图就明白了),则有边(i,j'),(i',j),(j,i'),(j',i)。
然后就是裸的2-SAT问题了。
注意存边的数组要开的够大。
代码:
var
n,m,f1,tot,e:longint;
side:array[1..1000000] of record
x,y,next:longint;
end;
x,y,f,last,belong:array[1..2000] of longint;
v:array[1..2000] of boolean;
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;
procedure add(x,y:longint);
begin
inc(e);
side[e].x:=x;
side[e].y:=y;
side[e].next:=last[x];
last[x]:=e;
end;
procedure init;
var
i,j:longint;
begin
readln(n,m);
for i:=1 to m do
begin
readln(x[i],y[i]);
if x[i]>y[i] then
begin
x[i]:=x[i] xor y[i]; y[i]:=x[i] xor y[i]; x[i]:=x[i] xor y[i];
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;
end;
procedure dfs(x:longint);
var
i:longint;
begin
v[x]:=false;
i:=last[x];
while i>0 do
with side[i] do
begin
if v[y] then dfs(y);
i:=next;
end;
if tot=0
then begin
inc(f1);
f[f1]:=x;
end
else belong[x]:=tot;
end;
procedure kosaraju;
var
i:longint;
begin
fillchar(v,sizeof(v),true);
for i:=1 to m*2 do
if v[i] then dfs(i);
fillchar(last,sizeof(last),0);
fillchar(v,sizeof(v),true);
for i:=1 to e do
add(side[i].y,side[i].x);
for i:=m*2 downto 1 do
if v[f[i]] then
begin
inc(tot);
dfs(f[i]);
end;
end;
procedure work;
var
i:longint;
begin
for i:=1 to m do
if belong[i]=belong[i+m] then
begin
writeln('the evil panda is lying again');
exit;
end;
writeln('panda is telling the truth...');
end;
begin
init;
kosaraju;
work;
end.