poj 3207 Ikki's Story IV - Panda's Trick 2-SAT

题意:平面上,一个圆,圆的边上按顺时针放着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.


你可能感兴趣的:(poj 3207 Ikki's Story IV - Panda's Trick 2-SAT)