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:
|
|
|
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
题目大意:
有一个有向图G(V,E),每条边e(a,b)上有一个位运算符op(AND,OR或XOR)和一个值c(0或1)。
问能不能在这个图上的每个点分配一个值X(0或1),使得每一条边e(a,b)满足 Xa op Xb = c
思路:
因为x的值不是0就是1,所以是2-sat类型的问题。
然后,开始苦逼地枚举每一种情况连边:
设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(当然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.