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

来源:互联网 发布:聚友网络股份有限公司 编辑:程序博客网 时间:2024/06/06 00:34

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

1 0
原创粉丝点击