浅谈2—SAT问题
来源:互联网 发布:mac双系统os系统消失 编辑:程序博客网 时间:2024/06/14 15:42
http://blog.csdn.net/pi9nc/article/details/11849843
2-SAT:
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
2
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
3
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
4
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
2-sat问题
在这篇文章我们提到过sat问题,sat问题是第一个npc问题,具体是这样的SAT全称是satisfiability,他是问对于一个合取范式,是否有一种输入使得他的输出是1,具体点就是类似这样的布尔表达式(x1 or x2 or x3)and(x3 or x4)and(not x1 or x5)对于所有的x是否有一种01取值,使得最后的结果是1。而2-sat问题就是每一个由or连接的子式都只包含两个变量,比如这样(x1 or x2) and (not x3 or x1),2-sat问题是有多项式解法的,而3-sat就是npc问题了,前段时间有人宣称证明了p=np就是因为他自己找到了3-sat的多项式解法,当然最后被证明解法是错误的。。。那么对于2-sat问题解法而言,经典的就是利用强连通分支的算法来解决,最近上的coursera上的algo2有个随机算法也很有趣这里我们也要讲一下。
先来看经典的利用强连通分支的图论解法。我们把每个变量x都拆成2个点,两个点x和~x分别表示这个点取1和这个点取0,所以最后我们就是在这2n个点中选择满足要求的n个点。对于每个子式,假设子式是(x1 or x2),对于2-sat问题而言我们需要每个子式都得1,也就是对于这个子式而言,x1和x2至少要取一个,对应于图中就是,如果我们取~x1就必须取x2,取~x2就必须取x1,所以我们就在图中从~x1到x2和从~x2到x1连两条有向边。同样的如果子式中有not也是类似方法,比如(not x1 or x2)那么就是X1到x2和~x2到~x1两条有向边。一开始的图片构成的图表示的这个式子。
(x0∨x2)∧(x0∨¬x3)∧(x1∨¬x3)∧(x1∨¬x4)∧(x2∨¬x4)∧(x0∨¬x5) ∧(x1∨¬x5)∧(x2∨¬x5)∧(x3∨x6)∧(x4∨x6)∧(x5∨x6)
构建好图之后对图求强连通分支,很显然的如果xi和~xi在同一个强连通分支中那么就是不存在解的。之后进行染色判定,强连通分支缩点之后,把所有的边反向,然后按照拓扑排序的顺序遍历节点,如果节点没有被染色,就涂成红色,然后把和这个点互斥的点(所谓互斥的点就是如果x和~x所在的点),以及这个点的子孙都涂成蓝色,这样取出红色的点就是满足条件的解。这里就不证明了,详细的可以看伍昱的《由对称性解2-SAT问题》和赵爽的《2-SAT解法浅析》两篇。看证明的时候注意对称性,就是说如果x,y在同一个连通分支,那么~x,~y也在同一个连通分支,如果x到y有路,那么~y到~x也有路,注意这个对称性的特点的话,那两篇文章里的证明也就不难看懂了。
talk is easy,show me the code,那么让我们看一下代码吧,这里就用poj 3648来举例。
- #include <cstdio>
- #include <cstring>
- const int maxn=10010;
- int n, m, nxt[maxn], head[maxn], pnt[maxn], ne, e, a, b, a0, b0;
- char c1, c2;
- int nnxt[maxn], nhead[maxn], npnt[maxn];
- int order[maxn], norder, id[maxn], v[maxn];
- int ans[maxn], op[maxn];
- void dfs(int d){
- v[d] = 1;
- for(int i=head[d]; i!=-1; i=nxt[i])
- if(!v[pnt[i]])
- dfs(pnt[i]);
- order[norder++] = d;
- }
- void ndfs(int d, int k){
- v[d] = 1;
- id[d] = k;
- for(int i=nhead[d]; i!=-1; i=nnxt[i])
- if(!v[npnt[i]])
- ndfs(npnt[i], k);
- }
- void addedge(int s, int t){
- pnt[e] = t; nxt[e] = head[s]; head[s] = e++;
- }
- void addnedge(int t, int s){
- npnt[ne] = s; nnxt[ne] = nhead[t]; nhead[t] = ne++;
- }
- void color(int d){
- ans[d] = 2;
- for(int i=head[d]; i!=-1; i=nxt[i])
- if(!ans[pnt[i]])
- color(pnt[i]);
- }
- int main(){
- while(1){
- norder = e = ne = 0;
- memset(head, -1, sizeof head);
- memset(nhead, -1, sizeof nhead);
- scanf("%d%d", &n, &m);
- if(!n&&!m)
- break;
- for(int i=0; i<m; ++i){
- scanf("%d%c%d%c", &a, &c1, &b, &c2);
- if(c1=='h')
- a0 = n+a;
- else{
- a0 = a;
- a += n;
- }
- if(c2=='h')
- b0 = n+b;
- else{
- b0 = b;
- b += n;
- }
- addedge(a0, b);
- addnedge(b, a0);
- addedge(b0, a);
- addnedge(a, b0);
- }
- addedge(0, n);
- addnedge(n, 0);
- memset(v, 0, sizeof v);
- for(int i=0; i<2*n; ++i)
- if(!v[i])
- dfs(i);
- int k=0;
- memset(v, 0, sizeof v);
- memset(id, -1, sizeof id);
- for(int i=norder-1; i>=0; --i)
- if(!v[order[i]])
- ndfs(order[i], k++);
- int mark = 1;
- for(int i=0; i<n; ++i)
- if(id[i]==id[i+n])
- mark = 0;
- if(!mark){
- printf("bad luck\n");
- continue;
- }
- for(int i=0; i<n; ++i){
- op[id[i]] = id[i+n];
- op[id[i+n]] = id[i];
- }
- e = norder = 0;
- memset(head, -1, sizeof head);
- memset(v, 0, sizeof v);
- memset(ans, 0, sizeof ans);
- for(int i=0; i<n; ++i)
- for(int j=nhead[i]; j!=-1; j=nnxt[j])
- addedge(id[i], id[npnt[j]]);
- for(int i=0; i<k; ++i)
- if(!v[i])
- dfs(i);
- for(int i=norder-1; i>=0; --i)
- if(!ans[order[i]]){
- ans[order[i]] = 1;
- color(op[order[i]]);
- }
- for(int i=1; i<n; ++i){
- if(ans[id[i]] == 1)
- printf("%dh", i);
- else
- printf("%dw", i);
- if(i<n-1)
- printf(" ");
- else
- printf("\n");
- }
- }
- return 0;
- }
- 浅谈2—SAT问题
- 浅谈2—SAT问题
- 浅谈2—SAT问题
- 浅谈2—SAT问题
- 浅谈2—SAT问题
- 浅谈2—sat问题
- 浅谈2-SAT问题
- 浅谈2-sat的问题的构造与求解
- UVALive 3713 浅谈2-SAT问题图论求解法
- 【2-SAT】2sat问题小结
- 2-SAT问题
- 2-SAT 问题
- 2-sat问题
- 2-sat 问题 模板
- 2-sat问题
- 2-sat问题总结
- 2-sat问题
- 2-sat问题
- Oracle 中查看用户建立的所有触发器
- android中NavigationDrawer的使用以及添加drawer切换时的动画效果
- 所谓的归并排序
- ActiveMQ持久化方式
- 假设一个集合有N篇文章
- 浅谈2—SAT问题
- Linux服务器下数据库操作
- zookeeper+activemq配置消息中间件集群 服务器配置
- SqlServer XML数据类型DML相关操作(图文结合)
- Asynctask个人总结
- 2-sat(2)随机算法
- 5.18
- reloc
- 2-sat(3)