码迷,mamicode.com
首页 > 其他好文 > 详细

hdu 4115 2-SAT

时间:2014-05-10 03:12:50      阅读:361      评论:0      收藏:0      [点我收藏+]

标签:style   blog   class   code   java   tar   

bubuko.com,布布扣
  1 /*
  2 题解:2-SAT
  3 一开始每一个round都有两种状态可选,并且选了每种状态有后面的限制其中一种选后另一状态的状态也被固定,
  4 十分符合2-SAT的用法;
  5 */
  6 #include <cstdio>
  7 #include <cstring>
  8 #include <iostream>
  9 #include <vector>
 10 #include <queue>
 11 
 12 #define clr(a,b) (memset(a,b,sizeof(a)))
 13 #define cpy(a,b) (memcpy(a,b,sizeof(b)))
 14 
 15 using namespace std;
 16 
 17 const int NV = 20005; // 点数要注意,后面是有两个点集
 18 const int NE = 200005; // 边也要注意加边的数量不只是限制条件的数目,因为一个限制条件可能要加几条边
 19 const int W = 0;
 20 const int R = 1;
 21 const int B = 2;
 22 
 23 int opp[NV];
 24 int in[NV];
 25 bool ans[NV];
 26 int col[NV];
 27 int n, nn, m;
 28 inline int Min(int a, int b) {return a < b ? a : b;}
 29 struct SCC {
 30     int deep,scc, top, SZ, n;
 31     struct edge {int v, next;} E[NE];
 32     int pre[NV], dep[NV], low[NV], id[NV], st[NV];
 33     bool in[NV];
 34     inline void init(int _n) {
 35         n = _n;
 36         clr(pre, -1);
 37         clr(dep, -1);
 38         clr(in,false);
 39         deep = scc = SZ = top = 0;
 40     }
 41     void tarjan(int u) {
 42         int v, i;
 43         dep[u] = low[u] = ++ deep;
 44         st[top++] = u;
 45 
 46         in[u] = true;
 47         for (i = pre[u]; i != -1; i = E[i].next) {
 48             v = E[i].v;
 49             if (dep[v] == -1) {
 50                 tarjan(v);
 51                 low[u] = Min(low[u], low[v]);
 52             }
 53             else if (in[v]) {
 54                 low[u] = Min(low[u], dep[v]);
 55             }
 56         }
 57         if (low[u] == dep[u]) {
 58             do {
 59                 v = st[--top];
 60                 in[v] = false;
 61                 id[v] = scc;
 62             } while (u != v);
 63             scc ++;
 64         }
 65     }
 66     inline void insert(int u, int v) {
 67         E[SZ].v = v;
 68         E[SZ].next = pre[u];
 69         pre[u] = SZ ++;
 70     }
 71     inline void solve() {
 72         for (int i = 0; i < n; i++) {
 73             if (dep[i] == -1) {
 74                 tarjan(i);
 75             }
 76         }
 77     }
 78 } G;
 79 int main(void) {
 80     int i, j;
 81     int x, y;
 82     int t;
 83     int alice[20005];
 84     scanf("%d",&t);
 85     for(int cas=1; cas<=t; cas++)
 86     {
 87         int n,m;
 88         scanf("%d%d", &n, &m);
 89         nn = n * 2; // 正反两个点集
 90         for (i = 0; i < nn; i++)
 91             opp[i] = (i ^ 1);
 92 
 93         G.init(nn);
 94         for(int i=0; i<nn; i+=2)
 95         {
 96             int cc;
 97             scanf("%d",&cc);
 98             switch(cc)
 99             {
100             case 1: alice[i] = 1,alice[opp[i]] = 2; break;
101             case 2: alice[i] = 2,alice[opp[i]] = 3; break;
102             case 3: alice[i] = 3,alice[opp[i]] = 1; break;
103             }
104         }
105         for (i = 0; i < m; i++) {
106             int a, b, k;
107             scanf("%d%d%d", &a, &b, &k);
108             a--;
109             a*=2;
110             b--;
111             b*=2;
112             /*
113             此处加边要注意是从0开始,而且偶数为该点集,奇数为对立点集
114             G.insert(x, opp[y]);
115             G.insert(y, opp[x]);
116             */
117             if (k)
118             {
119                 if (alice[a] == alice[b]) // 相等说明a必然要退出opp[b]才能得到正确结果,反过来亦然
120                 {
121                     G.insert(a,opp[b]);
122                     G.insert(b,opp[a]);
123                 }
124                 if (alice[a] == alice[opp[b]])
125                 {
126                     G.insert(a,b);
127                     G.insert(opp[b],opp[a]);
128                 }
129                 if (alice[opp[a]] == alice[b])
130                 {
131                     G.insert(opp[a],opp[b]);
132                     G.insert(b,a);
133                 }
134                 if (alice[opp[a]] == alice[opp[b]])
135                 {
136                     G.insert(opp[a],b);
137                     G.insert(opp[b],a);
138                 }
139             }
140             else
141             {
142                 if (alice[a] != alice[b])
143                 {
144                     G.insert(a,opp[b]);
145                     G.insert(b,opp[a]);
146                 }
147                 if (alice[a] != alice[opp[b]])
148                 {
149                     G.insert(a,b);
150                     G.insert(opp[b],opp[a]);
151                 }
152                 if (alice[opp[a]] != alice[b])
153                 {
154                     G.insert(opp[a],opp[b]);
155                     G.insert(b,a);
156                 }
157                 if (alice[opp[a]] != alice[opp[b]])
158                 {
159                     G.insert(opp[a],b);
160                     G.insert(opp[b],a);
161                 }
162             }
163         }
164         G.solve();
165         for (i = 0; i < nn; i += 2) {
166             if (G.id[i] == G.id[opp[i]]) {
167                 break;
168             }
169         }
170         if (i < nn) { // 不存在
171             printf("Case #%d: no\n",cas);
172         }
173         else
174             printf("Case #%d: yes\n",cas);
175     }
176     return 0;
177 }
bubuko.com,布布扣

 

hdu 4115 2-SAT,布布扣,bubuko.com

hdu 4115 2-SAT

标签:style   blog   class   code   java   tar   

原文地址:http://www.cnblogs.com/toufu/p/3719645.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!