题目: | Katu Puzzle | |
来源: | Pku 3678 | |
题目大意: | 有N个变量,为0或1,给出一堆逻辑关系,问是N个变量是否有一种取值方案。 | |
数据范围: | N (1 ≤ N ≤ 1000) and M,(0 ≤ M ≤ 1,000,000) | |
样例: | 4 4 0 1 1 AND 1 2 1 OR 3 2 0 AND 3 0 0 XOR | YES |
做题思路: | 把每个变量X看成两个点,I代表0,I'代表1。 2-sat,构图很强大。。。 | |
知识点: | 2-sat验证、kosaraju |
type
edge=record
y,next:longint;
end;
//====================================================
var
a1,a2:array[0..1000010]of edge;
first1,first2,q1,f:array[0..2020]of longint;
time,tot1,tot2,n,m:longint;
//=========================================================
procedure build1(x,y:longint);
begin
inc(tot1);
a1[tot1].y:=y;
a1[tot1].next:=first1[x];
first1[x]:=tot1;
end;
//==================================================================
procedure build2(x,y:longint);
begin
inc(tot2);
a2[tot2].y:=y;
a2[tot2].next:=first2[x];
first2[x]:=tot2;
end;
//============================================================
procedure init;
var
i,a,b,c,j,t:longint;
s:string;
ch:char;
begin
readln(n,m);
tot1:=0;tot2:=0;
fillchar(first1,sizeof(first1),0);
fillchar(first2,sizeof(first2),0);
for i:=1 to m do
begin
readln(a,b,c,ch,s);
inc(a);inc(b);
case s[1] of{<我发现kosaraju的缺点了,就是条件多了建图好麻烦>}
'A':if c=1 then
begin
build1(2*a,2*b);build2(2*b,2*a);
build1(2*a-1,2*a);build2(2*a,2*a-1);
build1(2*b,2*a);build2(2*a,2*b);
build1(2*b-1,2*a);build2(2*a,2*b-1);
end
else
begin
build1(2*a,2*b-1);build2(2*b-1,2*a);
build1(2*b,2*a-1);build2(2*a-1,2*b);
end;
'O':if c=1 then
begin
build1(2*a-1,2*b);build2(2*b,2*a-1);
build1(2*b-1,2*a);build2(2*a,2*b-1);
end
else
begin
build1(2*a-1,2*b-1);build2(2*b-1,2*a-1);
build1(2*b-1,2*a-1);build2(2*a-1,2*b-1);
build1(2*a,2*a-1);build2(2*a-1,2*a);
build1(2*b,2*b-1);build2(2*b-1,2*b);
end;
'X':if c=1 then
begin
build1(2*a,2*b-1);build2(2*b-1,2*a);
build1(2*b,2*a-1);build2(2*a-1,2*b);
build1(2*a-1,2*b);build2(2*b,2*a-1);
build1(2*b-1,2*a);build2(2*a,2*b-1);
end
else
begin
build1(2*a,2*b);build2(2*b,2*a);
build1(2*b,2*a);build2(2*a,2*b);
build1(2*a-1,2*b-1);build2(2*b-1,2*a-1);
build1(2*b-1,2*a-1);build2(2*a-1,2*b-1);
end;
end;
end;
end;
//===========================================================
procedure dfs1(x:longint);
var
t:longint;
begin
f[x]:=1;
t:=first1[x];
while t>0 do
begin
if f[a1[t].y]=0 then dfs1(a1[t].y);
t:=a1[t].next;
end;
inc(time);
q1[time]:=x;
end;
//==========================================================
procedure dfs2(x:longint);
var
t:longint;
begin
f[x]:=time;
t:=first2[x];
while t>0 do
begin
if f[a2[t].y]=0 then dfs2(a2[t].y);
t:=a2[t].next;
end;
end;
//==============================================================
procedure kosaraju;
var
i:longint;
begin
time:=0;
fillchar(f,sizeof(f),0);
for i:=1 to n*2 do
if f[i]=0 then dfs1(i);
time:=0;
fillchar(f,sizeof(f),0);
for i:=n*2 downto 1 do
if f[q1[i]]=0 then
begin
inc(time);
dfs2(q1[i]);
end;
end;
//=======================================================
procedure main;
var
i:longint;
begin
for i:=1 to n do
if(odd(i))and(f[2*i]=f[2*i-1]) then
begin
writeln('NO');
exit;
end;
writeln('YES');
end;
//==========================================================
begin
init;
kosaraju;
main;
end.
题目来源:
http://poj.org/problem?id=3678