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 }

 

posted @ 2018-08-02 11:00  Dillonh  阅读(328)  评论(0编辑  收藏  举报