1. 程式人生 > >POJ 3678 Katu Puzzle

POJ 3678 Katu Puzzle

tchar math set pen .org tor algo ++i truct

Katu Puzzle

鏈接

題意:

  有n個變量(每個變量只能是0或者1),m個等式,每個等式形如$x_i \ op \ x_j = c, \ op \in["and","or","xor"],c \in [0,1]$,問能否給n個變量賦值,滿足所有等式。

分析:

  2-sat問題。

  註意一下a&b=1的時候,要求a,b都為1,那麽就是說明“如果a為0,那麽a為1”,所以連邊a->a+n。

代碼:

#include<cstdio>
#include<algorithm>
#include<cstring>
#include
<iostream> #include<cmath> #include<cctype> #include<set> #include<queue> #include<vector> #include<map> using namespace std; typedef long long LL; inline int read() { int x=0,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch==-)f=-1
; for(;isdigit(ch);ch=getchar())x=x*10+ch-0;return x*f; } const int N = 2005; struct Edge{ int to, nxt; } e[2000005]; int head[N], dfn[N], low[N], sk[N], bel[N], En, Index, top, tot; bool vis[N]; inline void add(int u,int v) { ++En; e[En].to = v, e[En].nxt = head[u]; head[u] = En; } void
tarjan(int u) { dfn[u] = low[u] = ++Index; sk[++top] = u, vis[u] = 1; for (int i = head[u]; i; i = e[i].nxt) { int v = e[i].to; if (!dfn[v]) { tarjan(v); low[u] = min(low[u], low[v]); } else if (vis[v]) low[u] = min(low[u], dfn[v]); } if (low[u] == dfn[u]) { ++tot; do { vis[sk[top]] = 0; bel[sk[top]] = tot; top --; } while (sk[top + 1] != u); } } int main() { // freopen("1.txt", "r", stdin); int n = read(), m = read(); char op[10]; for (int i = 1; i <= m; ++i) { int a = read(), b = read(), c = read();scanf("%s",op); a ++, b ++; if (op[0] == A) { if (c == 0) add(a + n, b), add(b + n, a); else add(a, a + n), add(b, b + n); } else if (op[0] == O) { if (c == 0) add(a + n, a), add(b + n, b); else add(a, b + n), add(b, a + n); } else if (op[0] == X) { if (c == 0) add(a, b), add(b + n, a + n), add(b, a), add(a + n, b + n); else add(a, b + n), add(b, a + n), add(b + n, a), add(a + n, b); } } for (int i = 1; i <= n + n; ++i) if (!dfn[i]) tarjan(i); for (int i = 1; i <= n; ++i) { if (bel[i] == bel[i + n]) { puts("NO"); return 0; } } puts("YES"); return 0; }

POJ 3678 Katu Puzzle