您的位置:首页 > 其它

poj 3678

2016-06-06 20:04 183 查看
Description
Katu Puzzle ispresented as a directed graph G(V, E) with eachedge e(a, b) labeled by a boolean operator op (oneof AND, OR, XOR) and an integer c (0 ≤ c ≤1). One
Katu is solvable if one can find each vertex Vi avalue Xi (0 ≤ Xi ≤ 1)such that for each edge e(a, b) labeled by op and c,the following formula holds:
 Xa op Xb = c
The calculating rulesare:
AND
0
1
0
0
0
1
0
1
OR
0
1
0
0
1
1
1
1
XOR
0
1
0
0
1
1
1
0
Given a Katu Puzzle,your task is to determine whether it is solvable.
Input
The first linecontains two integers N (1 ≤ N ≤ 1000) and M,(0≤ M ≤ 1,000,000) indicating the number of vertices and edges.

The following M lines contain three integers a (0≤ a < N), b(0 ≤ b < N), c andan operator op each, describing the edges.
Output
Output a linecontaining "YES" or "NO".
SampleInput
4 4
0 1 1 AND
1 2 1 OR
3 2 0 AND
3 0 0 XOR
SampleOutput
YES
Hint
X0 = 1, X1 =1, X2 = 0, X3 = 1
 
题目大意:给m组关系(例如:0 1 1 AND,表示在B={b0,b1,……,bn}中,b0 and b1=1),问是否有方案使得所有条件成立。
 
分析:下面我们先把每个变量拆成两个点,一个表示值为true,一个表示值为false。然后定义连边(i,j),表示选了i必须选j。显然最后如果表示i为true和表示i为false的两个点在同一个强连通分量,那么就无解,否则就有解。按照逆拓扑序,逐个确定对应变量的值,最终就可以得到一个可行解。

对于本题,设i表示该变量为false,i’表示该变量为true。

i and j=1-------------->add(i,i')   add(j,j')

i and j=0-------------->add(i',j)   add(j',i)

i or j=1---------------->add(i,j')   add(j',i)

i or j=0---------------->add(i',i)   add(j',j)

i xor j=1--------------->add(i',j)   add(j',i)  add(i,j') add(j,i')

i xor j=0---------------> add(i,j)   add(i',j') add(j,i)  add(j',i')

 

因为只需要求是否有解,所以我用的是tarjan。

 

程序:

const

 maxn=2005;

 maxm=4000005;

type

 node=record

 x,y,next:longint;

end;

 

var

 n,m,e,cnt,d,num,tot:longint;

 ls,dfn,low,belong,stack:array [1..maxn] of longint;

 g:array [1..maxm] of node;

 instack:array [1..maxn] of boolean;

 

procedure add(x,y:longint);

begin

  inc(e);

  g[e].x:=x;

  g[e].y:=y;

  g[e].next:=ls[x];

  ls[x]:=e;

end;

 

procedure init;

var

  i,j,x,y,ans:longint;

  ch:char;

begin

 read(n,m);

 e:=0;

  for i:=1 to m do

   begin

     read(x,y,ans);

      inc(x); inc(y);

      repeat

       read(ch);

     until ch<>' ';

     readln;

     if ch='A' then

       if ans=1 then

         begin

           add(x,x+n);

           add(y,y+n);

         end

       else

         begin

           add(x+n,y);

           add(y+n,x);

          end;

     if ch='O' then

       if ans=1 then

         begin

           add(x,y+n);

           add(y,x+n);

         end

       else

         begin

           add(x+n,x);

           add(y+n,y);

         end;

     if ch='X' then

       if ans=1 then

         begin

           add(x,y+n);

           add(x+n,y);

            add(y,x+n);

            add(y+n,x);

         end

       else

         begin

            add(x,y);

            add(y,x);

            add(x+n,y+n);

            add(y+n,x+n);

         end;

   end;

end;

 

function min(x,y:longint):longint;

 begin

  if x<y then exit(x)

        else exit(y);

 end;

 

procedure tarjan(i:longint);

var j,t:longint;

 begin

 inc(d);

 dfn[i]:=d;

 low[i]:=d;

 inc(tot);

 stack[tot]:=i;

 t:=ls[i];

 instack[i]:=true;

 while t>0 do

  begin

   j:=g[t].y;

   if dfn[j]=0 then

    begin

     tarjan(j);

     low[i]:=min(low[i],low[j]);

    end

    else

     if instack[j] then

      low[i]:=min(low[i],dfn[j]);

   t:=g[t].next;

  end;

  if low[i]=dfn[i] then

  begin

   inc(num);

   repeat

    j:=stack[tot];

    instack[j]:=false;

    dec(tot);

    belong[j]:=num;

   until i=j;

  end;

 end;

 

procedure solve;

 var i:longint;

begin

 d:=0; num:=0;

 fillchar(dfn,sizeof(dfn),0);

 for i:=1 to n*2 do

  if dfn[i]=0 then

  tarjan(i);

end;

 

procedure output;

 var i:longint;

begin

  for i:=1 to n do

   if belong[i]=belong[i+n] then

   begin writeln('NO'); halt; end;

 writeln('YES');

end;

 

begin

 init;

 solve;

 output;

end.

 
 
 
 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: