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
# 例题
个 人队伍,每个队伍有一个队长
每个队伍要么队长回家,剩下两个留校,要么队长留校,剩下两人回家
给定 条限制,每条限制指定两个人 和 ,要求 和 不能同时留校
判断是否有合法方案
思路:
建立 个点的有向图, 点表示第 个人留校, 点表示第 个人回家
对于每个队伍 , , ,其中 为队长
和 的选择不同,按照 连边
和 的选择不同,按照 连边
和 的选择不同,按照 连边
对于每条限制 , ,两人不能同时留校
若 留校,则 回家:
若 留校,则 回家: