poj 3678 2-SAT

  1 /*
  2 题意:有n个数,要求满足XopY == c,操作的结果在表格中,尽管看不懂,但是实际上和平常的没有
  3 区别,问是否能有n个值使得所有操作都满足
  4 
  5 题解:2-SAT
  6 题目中有位的操作,以及对于数字的选取只有选与不选,而且是限制条件,这样就会比较容易想到是
  7 用2-SAT来做,关键在建图(http://blog.csdn.net/shuangde800/article/details/8876533)这个博文
  8 我觉得说得比较容易理解,其实就是将所有的点都拆成两个点,然后分别组成一个集合和一个对立的
  9 集合,最终我们是通过求强连通来寻找这些点是否与对立的点在同一连通分量中,如果同时出现在同
 10 一个强连通之中,则表示从一个点的状态可以推出它的对立状态,这显然是错的(例如x=1可以推导出
 11 x=-1),因此当我们要满足一个限制条件时,我们要做的就是通过加边使得这个条件可以满足,而且
 12 对于其它的状态则要通过加边来使得它不满足(即通过加边使得这些状态肯定不可能出现),因此在加
 13 边时有两个方向思考,一个是使限制条件满足,另一个是使其余状态不满足(两个应该等价吧,没有科
 14 学的证明),然后就是通过求强连通查找不可能满足的点:
 15 
 16 例子:
 17 (x,y)表示两个不同的点选与不选(即是正的状态还是对立状态)
 18 状态的组合有:(0,0),(0,1),(1,0),(1,1)
 19 要使得xANDy为1,则需要x和y都为1,亦即(1,1)成立,其余的三个组合都不成立,则通过加边使得
 20 另外三个状态不成立,要使(0,0)不满足,则需要加边(x,opp[y])表示当x为0时,y一定为1,这样
 21 (0,0)的状态就被否定了(注意反向(y,opp[x])也需要加边,因为要形成强连通,单向还不能保证会形
 22 成强连通,这里只是大概的理解,说得并不透彻),然后一直加边直至所有其它状态都矛盾。
 23 */
 24 #include <cstdio>
 25 #include <cstring>
 26 #include <vector>
 27 #include <queue>
 28 
 29 #define clr(a,b) (memset(a,b,sizeof(a)))
 30 #define cpy(a,b) (memcpy(a,b,sizeof(b)))
 31 
 32 using namespace std;
 33 
 34 const int NV = 4050;
 35 const int NE = 4000010;
 36 const int W = 0;
 37 const int R = 1;
 38 const int B = 2;
 39 
 40 int opp[NV];
 41 int in[NV];
 42 bool ans[NV];
 43 int col[NV];
 44 int nn;
 45 
 46 inline int Min(int a, int b) {return a < b ? a : b;}
 47 struct SCC {
 48     int deep,scc, top, SZ, n;
 49     struct edge {int v, next;} E[NE];
 50     int pre[NV], dep[NV], low[NV], id[NV], st[NV];
 51     bool in[NV];
 52     inline void init(int _n) {
 53         n = _n;
 54         clr(pre, -1);
 55         clr(dep, -1);
 56         clr(in,false);
 57         deep = scc = SZ = top = 0;
 58     }
 59     void tarjan(int u) {
 60         int v, i;
 61         dep[u] = low[u] = ++ deep;
 62         st[top++] = u;
 63 
 64         in[u] = true;
 65         for (i = pre[u]; i != -1; i = E[i].next) {
 66             v = E[i].v;
 67             if (dep[v] == -1) {
 68                 tarjan(v);
 69                 low[u] = Min(low[u], low[v]);
 70             }
 71             else if (in[v]) {
 72                 low[u] = Min(low[u], dep[v]);
 73             }
 74         }
 75         if (low[u] == dep[u]) {
 76             do {
 77                 v = st[--top];
 78                 in[v] = false;
 79                 id[v] = scc;
 80             } while (u != v);
 81             scc ++;
 82         }
 83     }
 84     inline void insert(int u, int v) {
 85         E[SZ].v = v;
 86         E[SZ].next = pre[u];
 87         pre[u] = SZ ++;
 88     }
 89     inline void solve() {
 90         for (int i = 0; i < n; i++) {
 91             if (dep[i] == -1) {
 92                 tarjan(i);
 93             }
 94         }
 95     }
 96 } G;
 97 inline void topsort() {
 98     int i, j, u, v;
 99     int now, id;
100     vector<int> vec[NV], gra[NV];
101     queue<int> Q, q;
102     clr(in, 0);
103     clr(col, 0);
104     for (i = 0; i < nn; i++) {
105         u = G.id[i];
106         gra[u].push_back(i);
107 
108         for (j = G.pre[i]; j != -1; j = G.E[j].next) {
109             v = G.id[ G.E[j].v ];
110             if (u != v) {
111                 vec[v].push_back(u);
112                 in[u]++;
113             }
114         }
115     }
116     for (i = 0; i < G.scc; i++) {
117         if (in[i] == 0) {
118             Q.push(i);
119         }
120     }
121     while (!Q.empty()) {
122         now = Q.front(),Q.pop();
123         if (col[now] != W) continue;
124         col[now] = R;
125         for (i = gra[now].size() - 1; i >= 0; i--) {
126             while (!q.empty()) q.pop();
127             q.push( G.id[ opp[ gra[now][i] ] ] );
128             while (!q.empty()) {
129                 id = q.front(),q.pop();
130                 if (col[id] == B) continue;
131                 col[id] = B;
132                 for (j = vec[id].size() - 1; j >= 0; j--) {
133                     q.push(vec[id][j]);
134                 }
135             }
136         }
137         for (i = vec[now].size() - 1; i >= 0; i--) {
138             if (--in[ vec[now][i] ] == 0) {
139                 Q.push(vec[now][i]);
140             }
141         }
142     }
143 }
144 int main(void) {
145     int i, j;
146     int x, y, c, n, m;
147     char op[10];
148     while (~scanf("%d%d", &n, &m)) {
149         nn = n * 2;
150         for (i = 0; i < nn; i++)
151             opp[i] = (i ^ 1);
152         G.init(nn);
153         for (i = 0; i < m; i++) {
154             scanf("%d%d%d%s", &x, &y, &c, op);
155             x *= 2;
156             y *= 2;
157             if(!strcmp(op, "AND")){  
158                 if(c){  
159                     G.insert(x, opp[y]),    G.insert(y, opp[x]);     //0, 0   
160                     G.insert(x, y),      G.insert(opp[y], opp[x]);   // 0, 1  
161                     G.insert(opp[x], opp[y]),  G.insert(y, x);       // 1, 0  
162                 }else{  
163                     G.insert(opp[x], y),    G.insert(opp[y], x);     // 1, 1   
164                 }  
165             }else if(!strcmp(op, "OR")){  
166                 if(c){  
167                     G.insert(x, opp[y]),    G.insert(y, opp[x]);     //0, 0   
168                 }else{  
169                     G.insert(x, y),      G.insert(opp[y], opp[x]);   // 0, 1  
170                     G.insert(opp[x], opp[y]),  G.insert(y, x);       // 1, 0  
171                     G.insert(opp[x], y),    G.insert(opp[y], x);     // 1, 1   
172                 }    
173             }else{ // XOR  
174                 if(c){  
175                     G.insert(x, opp[y]),    G.insert(y, opp[x]);     //0, 0   
176                     G.insert(opp[x], y),    G.insert(opp[y], x);     // 1, 1   
177                 }else{  
178                     G.insert(x, y),      G.insert(opp[y], opp[x]);   // 0, 1  
179                     G.insert(opp[x], opp[y]),  G.insert(y, x);       // 1, 0  
180                 }  
181             }
182         }
183         G.solve();
184         for (i = 0; i < nn; i += 2) {
185             if (G.id[i] == G.id[opp[i]]) {
186                 break;
187             }
188         }
189         if (i < nn)
190             printf("NO\n");
191         else
192             printf("YES\n");
193     }
194     return 0;
195 }

 

转载于:https://www.cnblogs.com/toufu/p/3661960.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值