Katu Puzzle(POJ3678+2-SAT问题+tarjan缩点)
题目链接:http://poj.org/problem?id=3678
题目:
题意:给你a,b,c,op,op为逻辑运算符或、与、异或,使得a op b = c,让你判断这些运算符是否存在矛盾,不存在输出YES,存在输出NO。
思路:2-SAT问题。2-SAT问题一般都是每个节点有两种选择,并且在节点中间将存在一定的限制,譬如a为1,那么b必须为1或a为0,b必须为1……而且当一个命题存在时,它的逆否命题必然存在(此处由命题为真,则其逆否命题也为真得证)。我们通过将这些关系转换成有向的边,通过tarjan缩点,我们可以通过判断同一个节点是否它的两种选择在同一个SCC中来决定是否存在矛盾。此题我们假设i为i节点取1,i+n为i节点取0,然后对c和op进行分类讨论,进行建图跑tarjan,从而解决此题。
代码实现如下:
1 #include <set> 2 #include <map> 3 #include <queue> 4 #include <stack> 5 #include <cmath> 6 #include <bitset> 7 #include <cstdio> 8 #include <string> 9 #include <vector> 10 #include <cstdlib> 11 #include <cstring> 12 #include <iostream> 13 #include <algorithm> 14 using namespace std; 15 16 typedef long long ll; 17 typedef pair<ll, ll> pll; 18 typedef pair<ll, int> pli; 19 typedef pair<int, ll> pil;; 20 typedef pair<int, int> pii; 21 typedef unsigned long long ull; 22 23 #define lson i<<1 24 #define rson i<<1|1 25 #define bug printf("*********\n"); 26 #define FIN freopen("D://code//in.txt", "r", stdin); 27 #define debug(x) cout<<"["<<x<<"]" <<endl; 28 #define IO ios::sync_with_stdio(false),cin.tie(0); 29 30 const double eps = 1e-8; 31 const int mod = 10007; 32 const int maxn = 1e6 + 7; 33 const double pi = acos(-1); 34 const int inf = 0x3f3f3f3f; 35 const ll INF = 0x3f3f3f3f3f3f3f; 36 37 int n, m, a, b, c, tot, cnt, num, top; 38 char op[5]; 39 int head[1007<<1]; 40 int vis[1007<<1], dfn[1007<<1], low[1007<<1], stc[1007<<1], p[1007<<1]; 41 42 struct edge { 43 int v, next; 44 }ed[maxn<<2]; 45 46 void addedge(int u, int v) { 47 ed[tot].v = v; 48 ed[tot].next = head[u]; 49 head[u] = tot++; 50 } 51 52 void tarjan(int x) { 53 dfn[x] = low[x] = ++num; 54 stc[++top] = x, vis[x] = 1; 55 for(int i = head[x]; ~i; i = ed[i].next) { 56 int y = ed[i].v; 57 if(!dfn[y]) { 58 tarjan(y); 59 low[x] = min(low[x], low[y]); 60 } else if(vis[y]) { 61 low[x] = min(low[x], low[y]); 62 } 63 } 64 if(dfn[x] == low[x]) { 65 int y; cnt++; 66 do { 67 y = stc[top--], vis[y] = 0; 68 p[y] = cnt; 69 } while(x != y); 70 } 71 } 72 73 int main() { 74 //FIN; 75 scanf("%d%d", &n, &m); 76 memset(head, -1, sizeof(head)); 77 for(int i = 1; i <= m; i++) { 78 scanf("%d%d%d%s", &a, &b, &c, op); 79 if(op[0] == 'A') { 80 if(c == 1) { 81 addedge(a + n, a); 82 addedge(b + n, b); 83 } else { 84 addedge(a, b + n); 85 addedge(b, a + n); 86 } 87 } else if(op[0] == 'O') { 88 if(c == 1) { 89 addedge(a + n, b); 90 addedge(b + n, a); 91 } else { 92 addedge(a, a + n); 93 addedge(b, b + n); 94 } 95 } else { 96 if(c == 1) { 97 addedge(a, b + n); 98 addedge(b, a + n); 99 addedge(a + n, b); 100 addedge(b + n, a); 101 } else { 102 addedge(a, b); 103 addedge(b, a); 104 addedge(a + n, b + n); 105 addedge(b + n, a + n); 106 } 107 } 108 } 109 for(int i = 0; i < 2 * n; i++) { 110 if(!dfn[i]) { 111 tarjan(i); 112 } 113 } 114 int flag = 1; 115 for(int i = 0; i < n; i++) { 116 if(p[i] == p[i+n]) { 117 flag = 0; 118 break; 119 } 120 } 121 if(flag) puts("YES"); 122 else puts("NO"); 123 return 0; 124 }
版权声明:本文允许转载,转载时请注明原博客链接,谢谢~