[POJ3678] Katu Puzzle | 2-SAT 入门
Description
Katu Puzzle is presented as a directed graph G ( V , E ) G(V, E) G(V,E) with each edge e ( a , b ) e(a, b) e(a,b) labeled by a boolean operator op ( o n e o f A N D , O R , X O R ) (one of AND, OR, XOR) (oneofAND,OR,XOR) and an integer c ( 0 ≤ c ≤ 1 ) c (0 ≤ c ≤ 1) c(0≤c≤1). One Katu is solvable if one can find each vertex V i Vi Vi a value X i ( 0 ≤ X i ≤ 1 ) Xi (0 ≤ Xi ≤ 1) 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
)
(1 ≤ N ≤ 1000)
(1≤N≤1000) and M,
(
0
≤
M
≤
1
,
000
,
000
)
(0 ≤ M ≤ 1,000,000)
(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
)
(0 ≤ a < N), b(0 ≤ b < N)
(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.
int n, m;
struct node {
int to,nex;
} e[maxm << 2];
int cnt = 0, head[maxn << 1];
bool inStk[maxn << 1];
int low[maxn << 1], dfn[maxn << 1],dfc, pos[maxn << 1];
void init() {
dfc = cnt = 0;
for(int i=0; i <=2* n; i++) {
head[i] = -1;
low[i] = dfn[i] = 0;
}
}
stack<int> stk;
void add(int u,int v) {
e[cnt].to = v;
e[cnt].nex = head[u];
head[u] = cnt ++;
}
int cntSCC;
void Tarjan(int u) {
// cout << u << endl;
dfn[u] = low[u] = ++ dfc;
inStk[u] = 1;
stk.push(u);
for(int i=head[u]; ~i; i=e[i].nex) {
itn to = e[i].to;
if(!dfn[to]) {
Tarjan(to);
low[u] = min(low[u],low[to]);
} else if(inStk[to] && !pos[to]) {
low[u] = min(low[u],dfn[to]);
}
}
if(low[u] == dfn[u]) {
int tp;
++ cntSCC;
do {
tp = stk.top();
stk.pop();
inStk[tp] = 0;
pos[tp] = cntSCC;
} while(tp != u);
}
}
int a,b,c;
string op;
int main() {
n=read,m=read;
init();
for(int i=1; i<=m; i++) {
a = read,b = read,c = read;
cin >> op;
int u=a * 2,u1=2 * a+1;
int v=b * 2,v1=2 * b+1;
if(op == "AND") {
if(c == 1) {/// u,v
add(u1,u);
add(v1,v);
} else {
// add(u,u1);
add(u,v1);
// add(v,u1);
add(v,u1);
}
} else if(op == "OR") {
if(c == 1) {
// add(u1,u);
add(u1,v);
// add(v1,v);
add(v1,u);
} else {
add(u,u1);
add(v,v1);
}
} else if(op == "XOR") {
if(c == 1) {
add(u,v1);
add(v,u1);
add(u1,v);
add(v1,u);
} else {
add(u,v);
add(v,u);
add(u1,v1);
add(v1,u1);
}
}
}
for(int i=0; i <= 2*n; i++) {
if(!dfn[i]) Tarjan(i);
}
for(int i=0; i <= 2*n; i++) {
if(pos[i] == pos[i+1]) {
puts("NO");
return 0;
}
i ++;
}
puts("YES");
return 0;
}