POJ 3678--Katu Puzzle(2-SAT)
感觉这题比较裸,表现出了2-sat的本质。
不过构图我想的还是太简单了,a&b=1我只连了 a1->b1,b1->a1,但其实是不对的。这样连,a0和b0可以同时选到。应该连a0->a1,b0->b1这样就能保证a0,b0都不被选到。或运算同理。
#include <algorithm>
#include <iostream>
#include <cstring>
#include <string>
#include <vector>
#include <bitset>
#include <cstdio>
#include <queue>
#include <stack>
#include <cmath>
#include <list>
#include <map>
#include <set>
#define pk(x) printf("%d\n", x)
using namespace std;
#define PI acos(-1.0)
#define EPS 1E-6
#define clr(x,c) memset(x,c,sizeof(x))
//#pragma comment(linker, "/STACK:102400000,102400000")
typedef long long ll;
const int N = 1010;
const int M = 2000020;
struct Edge {
int from, to, next;
} edge[M], edge2[M];
int head[N];
int cntE;
void addedge(int u, int v) {
edge[cntE].from = u; edge[cntE].to = v; edge[cntE].next = head[u]; head[u] = cntE++;
}
int dfn[N], low[N], idx;
int stk[N], top;
int in[N];
int kind[N], cnt;
void tarjan(int u)
{
dfn[u] = low[u] = ++idx;
in[u] = true;
stk[++top] = u;
for (int i = head[u]; i != -1; i = edge[i].next) {
int v = edge[i].to;
if (!dfn[v]) tarjan(v), low[u] = min(low[u], low[v]);
else if (in[v]) low[u] = min(low[u], dfn[v]);
}
if (low[u] == dfn[u]) {
++cnt;
while (1) {
int v = stk[top--]; kind[v] = cnt; in[v] = false;
if (v == u) break;
}
}
}
bool sat(int n) // 序号从0开始
{
for (int i = 0; i < n; ++i) if (!dfn[i]) tarjan(i);
for (int i = 0; i < n; i += 2) {
if (kind[i] == kind[i+n]) return false;
}
return true;
}
void init() {
memset(head, -1, sizeof head);
memset(dfn, 0, sizeof dfn);
memset(in, false, sizeof in);
cntE = idx = top = cnt = 0;
}
int main()
{
int n, m;
int a, b, c;
char op[10];
while (~scanf("%d%d", &n, &m)) {
init();
while (m--) {
scanf("%d%d%d%s", &a, &b, &c, op); // 0 1
if (*op == 'A') {//and
if (c == 1) {
addedge(a, a+n);
addedge(b, b+n);
} else {
addedge(a+n, b);
addedge(b+n, a);
}
} else if (*op == 'X') {//xor
if (c == 1) { //1^0=1;
addedge(a+n, b);
addedge(b+n, a);
addedge(a, b+n);
addedge(b, a+n);
} else {
addedge(a+n, b+n);
addedge(b+n, a+n);
addedge(a, b);
addedge(b, a);
}
} else {//or 0|0=0
if (c == 1) {
addedge(a, b+n);
addedge(b, a+n);
} else {
addedge(a+n, a);
addedge(b+n, b);
}
}
}
if (sat(n)) puts("YES");
else puts("NO");
}
return 0;
}