Katu Puzzle_poj3678_2-sat



Description

Katu Puzzle is presented as a directed graph G(V, E) with each edge e(a, b) labeled by a boolean operator op (one of AND, OR, XOR) and an integer c (0 ≤ c ≤ 1).(什么鬼名字O__O "…) One Katu is solvable if one can find each vertex Vi a value 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 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 a (0 ≤ a < N), b(0 ≤ b < N), c and an operator op each, describing the edges.

Output

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

Sample Input

4 4

0 1 1 AND

1 2 1 OR

3 2 0 AND

3 0 0 XOR

Sample Output

YES

Hint

X0 = 1, X1 = 1, X2 = 0, X3 = 1.

Source

POJ Founder Monthly Contest – 2008.07.27, Dagger

题目大意:

有一个有向图GVE),每条边ea,b)上有一个位运算符opANDORXOR)和一个值c01)。

问能不能在这个图上的每个点分配一个值X01),使得每一条边e(a,b)满足 Xa op Xb =  c

思路:

因为x的值不是0就是1,所以是2-sat类型的问题。

然后,开始苦逼地枚举每一种情况连边:

i表示该变量为falsei’表示该变量为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(当然Kosaraju也不是不行)。如果出现当前点的两个取值存在同一强连通分量说明冲突无解。

大半夜想起刷题的我是不是很勤奋很励志

源代码/pas:

 

type
  point=record
  x,y,next:longint;
end;
var
  n,m,t,maxE:longint;
  e:array[0..4000001]of point;
  ls,low,dfn,s,comp:array[0..5000]of longint;
  v:array[0..5000]of boolean;
function min(a,b:longint):longint;
begin
  min:=a;
  if b<a then
  min:=b;
end;
procedure add(x,y:Longint);
begin
  inc(maxE);
  e[maxE].x:=x;
  e[maxE].y:=y;
  e[maxE].next:=ls[x];
  ls[x]:=maxE;
End;
procedure tarjan(x:longint);
var
  i,y:longint;
begin
  inc(t);
  dfn[x]:=t;
  low[x]:=t;
  inc(s[0]);
  s[s[0]]:=x;
  v[x]:=true;
  i:=ls[x];
  while i>0 do
  begin
    y:=e[i].y;
    if dfn[y]=0 then
    begin
      tarjan(y);
      low[x]:=min(low[y],low[x]);
    end
    else
    if v[y] then
    low[x]:=min(low[x],dfn[y]);
    i:=e[i].next;
  end;
  if dfn[x]=low[x] then
  begin
    inc(comp[0]);
    repeat
      y:=s[s[0]];
      comp[y]:=comp[0];
      v[y]:=false;
      dec(s[0]);
    until x=y;
  end;
end;
procedure check;
var
  i:longint;
begin
  for i:=1 to n*2 do
  if dfn[i]=0 then
  tarjan(i);
  for i:=1 to n do
  if comp[i]=comp[i+n] then
  begin
    writeln('NO');
    halt;
  End;
  writeln('YES');
End;
procedure main;
var
  i,x,y,w:longint;
  st:string[1];
begin
  readln(n,m);
  for i:=1 to m do
  begin
    read(x,y,w);
    inc(x);
    inc(y);
    read(st);
    while st=' ' do read(st);
    readln;
    if st='A' then
      if w=1 then
      begin
        add(x,x+n);
        add(y,y+n);
      End
      else
      begin
        add(x+n,y);
        add(y+n,x);
      End;
    if st='O' then
      if w=1 then
      begin
        add(x,y+n);
        add(y,x+n);
      End
      else
      begin
        add(x+n,x);
        add(y+n,y);
      End;
    if st='X' then
      if w=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;
  check;
end;
begin
  main;
end.

 

转载于:https://www.cnblogs.com/olahiuj/p/5781309.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值