题意/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). 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".
题解/solution:
下面我们先把每个变量拆成两个点,一个表示值为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')
代码/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>