Katu Puzzle poj 3678 kosaraju+2-SAT

题意/Description:

 

  Katu Puzzle is presented as a directed graph G(VE) with each edge e(a, b) labeled by a boolean operator op (one of AND, OR, XOR) and an integer c (0 ≤ c ≤ 1). One Katu is solvable if one can find each vertex Vi a value Xi (0 ≤X≤ 1) such that for each edge e(a, b) labeled by op and c, the following formula holds:

     Xa op Xb = c

  The calculating rules are:

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 line contains 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 (0 ≤ a < N), b(0 ≤ b < N), c and an operator op each, describing the edges.

 

输出/Output

  Output a line containing "YES" or "NO".

 

题解/solution

 

下面我们先把每个变量拆成两个点,一个表示值为true,一个表示值为false。然后定义连边(i,j),表示选了i必须选j。显然最后如果表示itrue和表示ifalse的两个点在同一个强连通分量,那么就无解,否则就有解。按照逆拓扑序,逐个确定对应变量的值,最终就可以得到一个可行解。

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

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')

 

代码/Code

 

<span style="font-family:SimSun;">const
  maxE=100001;
  maxV=1001;
type
  arr=record
    x,y,next:longint;
  end;
var
  n,m,cnt,nm:longint;
  f:array [0..maxE] of arr;
  v:array [0..maxV] of boolean;
  ls,order,belong:array [0..maxV] of longint;
procedure add(o,p:longint);
begin
  inc(nm);
  with f[nm] do
    begin
      x:=o; y:=p;
      next:=ls[o];
      ls[o]:=nm;
    end;
end;

procedure init;
var
  i,num,x,y:longint;
  ch:char;
begin
  fillchar(ls,sizeof(ls),0);
  nm:=0;
  readln(n,m);
  for i:=1 to m do
    begin
      read(x,y,num);
      x:=x+1; y:=y+1;
      read(ch); readln(ch);
      if ch='A' then
        if num=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 num=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 num=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;

procedure dfs(p,ti:longint);
var
  t:longint;
begin
  v[p]:=true;
  t:=ls[p];
  while t>0 do
    with f[t] do
      begin
        if not v[y] then dfs(y,ti);
        t:=next;
      end;
  if ti=0 then
    begin
      inc(cnt);
      order[cnt]:=p;
    end else belong[p]:=cnt;
end;

procedure kosaraju;
var
  i,j,t:longint;
begin
  fillchar(v,sizeof(v),0);
  cnt:=0;
  for i:=1 to n+n do
    if not v[i] then dfs(i,0);
  fillchar(ls,sizeof(ls),0);
  fillchar(v,sizeof(v),0);
  t:=nm; cnt:=0; nm:=0;
  for i:=1 to t do
    add(f[i].y,f[i].x);
  for i:=n+n downto 1 do
    begin
      j:=order[i];
      if not v[j] then
        begin
          inc(cnt);
          dfs(j,1);
        end;
    end;
end;

procedure print;
var
  i:longint;
begin
  for i:=1 to n do
    if belong[i]=belong[i+n] then
      begin
        write('NO'); halt;
      end;
  write('YES');
end;

begin
  init;
  kosaraju;
  print;
end.
</span>



posted @ 2016-06-06 16:40  猪都哭了  阅读(162)  评论(0编辑  收藏  举报