2-SAT问题
导引: , , 三人中有两个女生
如果 是男生,那么 一定是女生:
和 性别相同
求 三人的性别
# 2 - SAT问题
# 定义
要确定N个bool类型的值,使得其满足所有的限制关系(每个限制关系最多只对两个bool变量进行限制)
2-SAT问题是有多项式解法的,而3-SAT问题就是npc问题
# 判断是否有解
建立2N个点的有向图,不妨设
点表示
点表示
一条 的有向边表示如果选择了 ,那么一定要选择
不能出现
判断i和i'是否位于同一强连通分量即可
# 输出可行方案
如果从 点出发可以到达 点,则旋律i会导致选 ,矛盾,因此只能选
Kosaraju算法在求强连通分量时顺带求出了一个遍历顺序
只需要比较i和i'所属强连通分量在q中位置的前后关系即可构造出可行方案
# 一元限制的构图方案
限制:
连边:
表示如果 选了 那么 必须要是
# 二元限制的构图方案
一条边 的含义:若 则
命题”若 则 “的逆否命题为”若非 则非 “
命题于逆否命题等价
所以在建 , 也要建
所以对于每条二元限制,将其对应的命题与逆否命题的边连上,缺一不可
建图例:
限制:
(有一个满足 就行)
建图例:
限制:
(两者都要 回到一元限制关系)
建图例:
限制:
(两个没有同时满足)
建图例:
限制:
(两个都要满足)
建图例:
限制:
(两个情况不同)
建图例:
限制:
(两个情况相同)
# 例题
有 对夫妻被邀请参加一个聚会,因为场地的问题,每对夫妻中只有 人可以列席
在 个人中,某些人之间有着很大矛盾(夫妻之间没有),主办方希望有矛盾的两个人不能同时出现在聚会上
问有没有可能回有 个人同时列席?
思路:
建立 个点的图,i点表示第i对夫妻是丈夫到场, 点表示妻子到场
如果 和 矛盾,则可以表示”若 则非 “、”若 则非 “。
# 强连通分量求出后的处理
bool res = 1;
for(int i = 0; i < N; i ++){
if(nod[i] == nod[trans(i)]){
res = 0;
break;
}
}
if(res) cout << "YES" << endl;
else cout << "NO" << endl;
//i'可以使用便宜量,表示为i + n(与带权并查集类似)
2
3
4
5
6
7
8
9
10
11
# 例题
个 人队伍,每个队伍有一个队长
每个队伍要么队长回家,剩下两个留校,要么队长留校,剩下两人回家
给定 条限制,每条限制指定两个人 和 ,要求 和 不能同时留校
判断是否有合法方案
思路:
建立 个点的有向图, 点表示第 个人留校, 点表示第 个人回家
对于每个队伍 , , ,其中 为队长
和 的选择不同,按照 连边
和 的选择不同,按照 连边
和 的选择不同,按照 连边
对于每条限制 , ,两人不能同时留校
若 留校,则 回家:
若 留校,则 回家: