[除草]关于2-sat——POJ上的几道题
2013-02-26 11:50
183 查看
最近看到一个很有意思的问题——2-sat问题,其基本定义就是说有n个布尔变量,给定m组变量之间的关系,每组最多只包含两个变量,求一种方案使得各个关系均满足。
解法:如果去掉“每组最多只包含两个变量”的条件,那么它就成了NPC问题,但是2-sat却有着非常巧妙的多项式解——将n个布尔变量表示成2n个点,分别表示该变量为真或为假。将必须同时选的两个点之间连上一条边;这样在这个图的一个强连通分量内的点就是必须都选的,如果一个强连通分量包含了x与!x,那么这个2-sat显然是无解的,否则一定可以根据拓扑序来选定一些点使该2-sat成立。
推荐两篇论文:华东师大一附中赵爽的《2-sat解法浅析》和《由对称性解决2-sat问题》,有关算法复杂度分析,具体实现,正确性证明可以参考论文。在此向论文作者致敬!!
下面是一些2-sat的题目(刷了很久才搞完,弱炸了T T):
poj3207 Ikki's Story IV - Panda's Trick:
在圆上给n个点,之间连了一些边,每条边要么在里面,要么在外面,要求判断这些边是否一定有交点。
“每条边要么在里面,要么在外面”,可以根据这个建立2-sat模型。枚举任意两条边,如果有交点那么就说明不能同时为里面或者外面,根据这个建图,再跑一遍模板就可以了。
poj3678 Katu Puzzle
真·模板题。给定一些两个变量的关系(and,or,not等),要求它们成立。直接根据关系建图,再跑一遍模板就可以了。
poj3683 Priest John's Busiest Day
给定一些区间,要求在它们的头或尾各选一个固定长度的子区间,并且各个子区间不能相交,求是否可行并给出一组可行的方案。根据“每个区间都必须在头或在尾选一个固定的区间”建立2-sat模型,跑模板即可。
ps 其实这道题的核心不在2-sat,而是判断两个区间是否相交…………我写得无比复杂,后来终于发现可以根据区间端点的差值就可以做了……
ps ps 2:00-2:30 2:30-3:00这两个区间没有交集,被坑了一次。
poj3648 Wedding
相当无语的题……有n对夫妻参加一次婚礼,它们和新郎新娘分别坐在桌子两边,要求夫妻(包括新郎新娘)不能坐在一端,且它们之间有些有通奸关系(同性和异性的都可能),有通奸关系的两人不能同时坐在新娘的对面。
求是否可行和可行解。
夫妻不能同时选在一边,有通奸关系的两人至少有一人在新娘这边。根据这个关系建图就可以做了。
ps 被坑爆了,一开始以为n对都是新婚的…………后来看对题了又没想到新郎新娘也会有通奸关系………………相当无语………………什么婚礼啊………………………………
poj2723 Get Luffy Out
给出n对钥匙和m扇门,每扇门有两把锁,每种类型的锁必须要对应的钥匙才能打开(一一对应,且每种钥匙只有一把);每扇门只需要开启一把锁就可以打开;每对钥匙只要用掉其中一把就不能用另一把;门必须按顺序打开;
求最多能开多少扇门。
二分答案,就变成了检验这些钥匙能否按顺序打开k扇门。每扇门如果不用开第一把锁(即不使用能开第一把锁的钥匙),就必须开第二把锁(即使用能开第二把锁的钥匙);每对钥匙如果用掉一把,就不能用另一把。
根据钥匙建图就可以检验了。
ps 被坑了一次,检验答案k的时候只需要为前k扇门建边,但是要为所有的钥匙对建边。
poj2749 Building roads
有n个牛棚,两个交换站。每个牛棚必须建一条到某一个交换站的边,两个交换站之间也有一条边。某些牛棚不能被连在同一个交换站上,某些必须连在同一个交换站上。距离定义为曼哈顿距离。
求牛棚之间距离最大值的最小值。
二分最大值u,根据每两个牛棚之间的距离和给出的关系进行一些制约(如两个牛棚到交换站1的距离大于u,那么它们就不能被同时连在左边等),细节较繁琐,反正我写了180+行,有高手100行之内
搞定的…………没办法,本人太弱了TT。
ps 这题最开始数组开小了(应该是2*n^2),但是交上去却是WA而不是RE…………害得我搞了好久…………
最后,附上本人弱爆的模板,望各路神牛批评指出缺陷:
View Code
解法:如果去掉“每组最多只包含两个变量”的条件,那么它就成了NPC问题,但是2-sat却有着非常巧妙的多项式解——将n个布尔变量表示成2n个点,分别表示该变量为真或为假。将必须同时选的两个点之间连上一条边;这样在这个图的一个强连通分量内的点就是必须都选的,如果一个强连通分量包含了x与!x,那么这个2-sat显然是无解的,否则一定可以根据拓扑序来选定一些点使该2-sat成立。
推荐两篇论文:华东师大一附中赵爽的《2-sat解法浅析》和《由对称性解决2-sat问题》,有关算法复杂度分析,具体实现,正确性证明可以参考论文。在此向论文作者致敬!!
下面是一些2-sat的题目(刷了很久才搞完,弱炸了T T):
poj3207 Ikki's Story IV - Panda's Trick:
在圆上给n个点,之间连了一些边,每条边要么在里面,要么在外面,要求判断这些边是否一定有交点。
“每条边要么在里面,要么在外面”,可以根据这个建立2-sat模型。枚举任意两条边,如果有交点那么就说明不能同时为里面或者外面,根据这个建图,再跑一遍模板就可以了。
poj3678 Katu Puzzle
真·模板题。给定一些两个变量的关系(and,or,not等),要求它们成立。直接根据关系建图,再跑一遍模板就可以了。
poj3683 Priest John's Busiest Day
给定一些区间,要求在它们的头或尾各选一个固定长度的子区间,并且各个子区间不能相交,求是否可行并给出一组可行的方案。根据“每个区间都必须在头或在尾选一个固定的区间”建立2-sat模型,跑模板即可。
ps 其实这道题的核心不在2-sat,而是判断两个区间是否相交…………我写得无比复杂,后来终于发现可以根据区间端点的差值就可以做了……
ps ps 2:00-2:30 2:30-3:00这两个区间没有交集,被坑了一次。
poj3648 Wedding
相当无语的题……有n对夫妻参加一次婚礼,它们和新郎新娘分别坐在桌子两边,要求夫妻(包括新郎新娘)不能坐在一端,且它们之间有些有通奸关系(同性和异性的都可能),有通奸关系的两人不能同时坐在新娘的对面。
求是否可行和可行解。
夫妻不能同时选在一边,有通奸关系的两人至少有一人在新娘这边。根据这个关系建图就可以做了。
ps 被坑爆了,一开始以为n对都是新婚的…………后来看对题了又没想到新郎新娘也会有通奸关系………………相当无语………………什么婚礼啊………………………………
poj2723 Get Luffy Out
给出n对钥匙和m扇门,每扇门有两把锁,每种类型的锁必须要对应的钥匙才能打开(一一对应,且每种钥匙只有一把);每扇门只需要开启一把锁就可以打开;每对钥匙只要用掉其中一把就不能用另一把;门必须按顺序打开;
求最多能开多少扇门。
二分答案,就变成了检验这些钥匙能否按顺序打开k扇门。每扇门如果不用开第一把锁(即不使用能开第一把锁的钥匙),就必须开第二把锁(即使用能开第二把锁的钥匙);每对钥匙如果用掉一把,就不能用另一把。
根据钥匙建图就可以检验了。
ps 被坑了一次,检验答案k的时候只需要为前k扇门建边,但是要为所有的钥匙对建边。
poj2749 Building roads
有n个牛棚,两个交换站。每个牛棚必须建一条到某一个交换站的边,两个交换站之间也有一条边。某些牛棚不能被连在同一个交换站上,某些必须连在同一个交换站上。距离定义为曼哈顿距离。
求牛棚之间距离最大值的最小值。
二分最大值u,根据每两个牛棚之间的距离和给出的关系进行一些制约(如两个牛棚到交换站1的距离大于u,那么它们就不能被同时连在左边等),细节较繁琐,反正我写了180+行,有高手100行之内
搞定的…………没办法,本人太弱了TT。
ps 这题最开始数组开小了(应该是2*n^2),但是交上去却是WA而不是RE…………害得我搞了好久…………
最后,附上本人弱爆的模板,望各路神牛批评指出缺陷:
View Code
#include<cstdio> #include<cstdlib> #include<cstring> #include<algorithm> using namespace std; #define _y(x) (x<<1) #define _n(x) (x<<1|1) const int maxn=2010; const int maxm=4000010; struct node { int end; node *next; }edge[maxm],*head[maxn],*p; int dfn[maxn],low[maxn],stk[maxn],color[maxn],n,colo,idx,all,top; bool inS[maxn]; inline void add_edge(int x,int y) { p=&edge[++all],p->end=y,p->next=head[x],head[x]=p; } void tarjan(int u) { dfn[u]=low[u]=++idx; inS[stk[++top]=u]=true; for (node *p=head[u];p;p=p->next) if (!dfn[p->end]) { tarjan(p->end); low[u]=min(low[u],low[p->end]); } else if (inS[p->end]) { low[u]=min(low[u],dfn[p->end]); } if (low[u]==dfn[u]) { int v;++colo; do { inS[v=stk[top--]]=false; color[v]=colo; } while (u!=v); } } int main() { int x,y,z,m; char op[5]; scanf("%d%d",&n,&m); while (m--) { scanf("%d%d%d%s",&x,&y,&z,op),++x,++y; if (op[0]=='A') { if (z) { add_edge(_y(x),_y(y)); add_edge(_y(y),_y(x)); add_edge(_n(x),_y(x)); add_edge(_n(y),_y(y)); } else { add_edge(_y(x),_n(y)); add_edge(_y(y),_n(x)); } } else if (op[0]=='O') { if (z) { add_edge(_n(x),_y(y)); add_edge(_n(y),_y(x)); } else { add_edge(_n(x),_n(y)); add_edge(_n(y),_n(x)); add_edge(_y(x),_n(x)); add_edge(_y(y),_n(y)); } } else if (op[0]=='X') { if (z) { add_edge(_y(x),_n(y)); add_edge(_y(y),_n(x)); add_edge(_n(y),_y(x)); add_edge(_n(x),_y(y)); } else { add_edge(_y(x),_y(y)); add_edge(_y(y),_y(x)); add_edge(_n(x),_n(y)); add_edge(_n(y),_n(x)); } } } x=n<<1|1; for (int i=2;i<=x;++i) if (!dfn[i]) tarjan(i); for (int i=1;i<=n;++i) if (color[_y(i)]==color[_n(i)]) { puts("NO"); return 0; } puts("YES"); return 0; }
相关文章推荐
- poj 几道简单的搜索题 (一)
- POJ - 3678 Katu Puzzle (2-SAT)
- poj 3678 2-sat
- POJ 2296 Map Labeler(2-SAT)
- POJ 3207 Ikki's Story IV - Panda's Trick(2-SAT)
- 【2-SAT】POJ 3207
- 几道关于cocos2dx的面试题
- poj 几道简单的dp题
- POJ-3648 Wedding 2sat
- POJ 3207 Ikki's Story IV - Panda's Trick 2-SAT
- poj 3648 Wedding 2_SAT
- POJ 3207 - Ikki's Story IV - Panda's Trick 构图2-sat
- POJ 2296 Map Labeler (二分+2-SAT判)
- POJ 2-SAT 六题
- poj 3678 Katu Puzzle(Two Sat)
- POJ 2749 || HDU 1815 Building roads 2-sat
- POJ 3648 Wedding 2-SAT
- POJ 3207 Ikki's Story IV - Panda's Trick (2-SAT)
- POJ-3683-Priest John's Busiest Day(2-SAT染色)
- POJ 3207 Ikki's Story IV - Panda's Trick (2-SAT)