2-sat问题
来源:互联网 发布:淘宝免费开店要钱吗 编辑:程序博客网 时间:2024/06/03 18:40
2-sat问题:
给定一堆约束条件,每个都形如“xi为真/假或xj为真/假”,即:xi为真/假和xj为真/假中必有一个成立,现在问是否可以全部满足
思路:
- 可以把xi为真看成两个节点:2i, 2i+1(因为2i^1=2i+1,可以互相转化)
- 假如说约束条件为“xi为真或xj为假”,那么2i表示“xi为真”为真,2i+1表示“xi为真”为假;2j表示“xj为假”为真,2j+1表示”xj为假“为假
- 则,由2j+1为真可以推出2i为真,同理,由2i+1可以推出2j为真
- 所以,可以从2j+1到2i;2i+1到2j连两条有向边
- 对于起点u,可以假设他为真,并对他进行深搜,如果过程中发现有点的两个结点都为真,则不能
- 再假设他为假,再深搜,如果他还是不能,则不能建图
例题:
有n架飞机要着陆,每个都可以选择早着陆或晚着陆,请安排着陆方式,要求着陆时间差值的最小值最大
- 思路:”最小值最大“可以用二分,问题即可转化成着陆时间差值不大于mid是否成立,所以着陆时间小于mid的两个点,至多有一个成立,等价于这两个点的补至少有一个成立,这样就转化为了2-sat
代码:(调了一个上午,参考刘汝佳《算法竞赛入门经典训练指南》)
#include<cstdio>#include<cstring>#include<string>#include<vector>#include<cstdlib>#include<iostream>#include<algorithm>using namespace std;const int MAXN = 2000 + 10;struct twosat{ vector<int> G[MAXN*2]; bool mark[MAXN*2]; int s[MAXN*2], c; int n; //外面的n bool dfs(int u) { if(mark[u^1]) return false; if(mark[u]) return true; mark[u] = true; s[c++] = u; for(int i = 0; i < G[u].size(); i++) { int v = G[u][i]; if(!dfs(v)) return false; } return true; } void init(int n) { this->n/*这个是外面的n*/ = n; //将外面的n赋值为里面的n for(int i = 0; i < 2*n; i++) G[i].clear(); memset(mark, 0, sizeof(mark)); } void add(int x, int xval, int y, int yval) //x == xval or y == yval { x = 2 * x + xval; //2i y = 2 * y + yval; //2j G[x^1].push_back(y); G[y^1].push_back(x); } bool solve() { for(int i = 0; i < 2*n; i += 2) if(!mark[i] && !mark[i+1]) { c = 0; if(!dfs(i)) { while(c > 0) mark[s[--c]] = false; //如果深搜它不成功,则所有的假设都错误 if(!dfs(i+1)) return false; //如果假设他为真假都不对,不能成图 } } return true; }};twosat solver;int t[MAXN][2], n;bool test(int mid){ solver.init(n); for(int i = 0; i < n; i++) for(int a = 0; a <= 1; a++) for(int j = i + 1; j < n; j++) for(int b = 0; b <= 1; b++) { if(abs(t[i][a] - t[j][b]) < mid) solver.add(i, a^1, j, b^1); } return solver.solve();}int main(){ cin >> n; int l = 0, r = 0; for(int i = 0; i < n; i++) for(int a = 0; a <= 1; a++) { cin >> t[i][a]; r = max(r, t[i][a]); } while(l < r) { int mid = l + (r-l+1)/2; //令相邻两个着陆时间都 大于等于mid //时间差小于mid的两个时间不能同时满足 if(test(mid)) l = mid; else r = mid-1; } cout << l; return 0;}
0 0
- 【2-SAT】2sat问题小结
- 2-SAT问题
- 2-SAT 问题
- 2-sat问题
- 2-sat 问题 模板
- 2-sat问题
- 2-sat问题总结
- 2-sat问题
- 2-sat问题
- 2-sat问题
- 2-SAT 问题
- 2-SAT问题
- 2-sat问题
- 2-SAT问题
- 2-SAT问题
- 2-sat问题
- 2-SAT问题
- 2-SAT问题(LA3713)
- ImportError: No module named _tkinter, please install the python-tk package
- 极光推送的角标问题
- 卷积神经网络_(1)卷积层和池化层学习
- 去除数组中空值的方法
- 23种设计模式藏宝图
- 2-sat问题
- java中Map,List与Set的区别
- (三)React Native中Navigation组件的快速入门
- “无法启动此程序,因为计算机中丢失 MSVCR110.dll。尝试重新安装该程序以解决此问题。”
- 百度地图之定位篇
- 连接
- Redis集群的配置
- CvRect、RECT和Rect
- 详解Javascript中prototype属性