2-SAT
部分转自https://blog.csdn.net/jarjingx/article/details/8521690
博主讲的真的太棒了
2-sat
定义:
有一些集合,每个集合里面有且仅有两个元素,且不能同时选取两个元素,集合间的元素存在一定的选择关系,求解可行解以及可行方案
// 如果元素最多的集合里面有k个元素,则称其为k-sat问题,可以证明是NP完全问题(出门右转百度百科)
方法:
1.连边
2.tarjan缩点,连反边
3.判断可行性,即同一集合中的两点是否属于一个强联通分量
4.拓扑排序,若当前节点没有被访问过,则选择该点,不选择其他的点
5.构造方案
连边
算法本身并不难,关键在于连边,充分理解好边的概念:a->b表示选a必选b
a,b不能同时取 :a->b',b->a'
a,b不能同时不取 :a'->b,b'->a
a,b要么都取要么都不取 :a->b,b->a,a'->b',b'->a'
a,b必须同时取 :同上
a必须取 :a->a'
缩点
tarjan缩点,将所有边反过来
#以下将强联通分量简称为分量
判断可行性
枚举每个集合,判断其两个元素是否在同一个分量内,若在同一个内则不可行
拓扑排序
将缩点后的分量进行排序
构造方案
按照拓扑后的顺序依次访问所有分量,若某个分量没有被访问则将其标记为"选择",不传递"选择"标记,将被选分量的对立分量标记为"不选择",将其"不选择"的标记沿着传递(注意边已经反过来了)