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 }
View Code

 

posted @ 2018-10-09 16:54  mrclr  阅读(279)  评论(0编辑  收藏  举报