POJ 3678 Katu Puzzle
一个比较经典的的2-SAT问题。
因为c只有0或1,所以每个数的取值只有0或1.
把每一个点拆点:x0表示x取0,x1表示x取1.
然后分情况连边:
1.x AND y == 0:连(x1, y0), (y1, x0)
2.x AND y == 1:连(x0, x1), (y0, y1)。这个时候x和y必须都取1,刚开始我想的是(x1, y1), (y1, x1),但这么连是错的,因为显然这两个点是在一个强连通分量中,那么也就可能同时等于0.所以我们考虑不可能的情况:x = 0,那么肯定gg,所以连边(x0, x1)。因为这本身就是一个矛盾的情况。
3.x OR y == 0:连(x1, x0), (y1, y0).
4.x OR y ==1:连(x0, y1), (y0, x1).
5.x XOR y == 0:连(x0, y0), (x1, y1), (y0, x0), (y1, x1).
6.x XOR y == 1:连(x0, y1), (x1, y0), (y0, x1), (y1, x0).
1 #include<cstdio> 2 #include<iostream> 3 #include<algorithm> 4 #include<cmath> 5 #include<cstring> 6 #include<cstdlib> 7 #include<cctype> 8 #include<stack> 9 #include<queue> 10 #include<vector> 11 using namespace std; 12 #define enter puts("") 13 #define space putchar(' ') 14 #define Mem(a, x) memset(a, x, sizeof(a)) 15 #define rg register 16 typedef long long ll; 17 typedef double db; 18 const int INF = 0x3f3f3f3f; 19 const db eps = 1e-8; 20 const int maxn = 1e3 + 5; 21 const int maxm = 1e6 + 5; 22 inline ll read() 23 { 24 ll ans = 0; 25 char ch = getchar(), las = ' '; 26 while(!isdigit(ch)) las = ch, ch = getchar(); 27 while(isdigit(ch)) ans = ans * 10 + ch - '0', ch = getchar(); 28 if(las == '-') ans = -ans; 29 return ans; 30 } 31 inline void write(ll x) 32 { 33 if(x < 0) putchar('-'), x = -x; 34 if(x >= 10) write(x / 10); 35 putchar(x % 10 + '0'); 36 } 37 38 int n, m; 39 char ch[5]; 40 struct Edge 41 { 42 int to, nxt; 43 }e[maxm << 2]; 44 int head[maxn << 1], ecnt = 0; 45 void addEdge(int x, int y) 46 { 47 e[++ecnt].to = y; 48 e[ecnt].nxt = head[x]; 49 head[x] = ecnt; 50 } 51 52 stack<int> st; 53 bool in[maxn << 1]; 54 int dfn[maxn << 1], low[maxn << 1], cnt = 0; 55 int col[maxn << 1], ccol = 0; 56 void tarjan(int now) 57 { 58 dfn[now] = low[now] = ++cnt; 59 st.push(now); in[now] = 1; 60 for(int i = head[now]; i; i = e[i].nxt) 61 { 62 if(!dfn[e[i].to]) 63 { 64 tarjan(e[i].to); 65 low[now] = min(low[now], low[e[i].to]); 66 } 67 else if(in[e[i].to]) low[now] = min(low[now], dfn[e[i].to]); 68 } 69 if(dfn[now] == low[now]) 70 { 71 int x; ++ccol; 72 do 73 { 74 x = st.top(); st.pop(); 75 col[x] = ccol; in[x] = 0; 76 }while(x != now); 77 } 78 } 79 80 int main() 81 { 82 n = read(); m = read(); 83 for(int i = 1; i <= m; ++i) 84 { 85 int x = read(), y = read(), c = read(); 86 x++; y++; 87 scanf("%s", ch); 88 if(ch[0] == 'A') 89 { 90 if(c) 91 { 92 addEdge(x, x + n); 93 addEdge(y, y + n); 94 } 95 else 96 { 97 addEdge(x + n, y); 98 addEdge(y + n, x); 99 } 100 101 } 102 else if(ch[0] == 'O') 103 { 104 if(c) 105 { 106 addEdge(x, y + n); 107 addEdge(y, x + n); 108 } 109 else 110 { 111 addEdge(x + n, x); 112 addEdge(y + n, y); 113 } 114 } 115 else 116 { 117 addEdge(x, y + c * n); addEdge(x + n, y + (c ^ 1) * n); 118 addEdge(y, x + c * n); addEdge(y + n, x + (c ^ 1) * n); 119 } 120 } 121 for(int i = 1; i <= (n << 1); ++i) if(!dfn[i]) tarjan(i); 122 for(int i = 1; i <= n; ++i) 123 if(col[i] == col[n + i]) {printf("NO\n"); return 0;} 124 printf("YES\n"); return 0; 125 }