2-SAT 问题与解法小结
这个算法十分的奇妙qwq... 将一类判定问题转换为图论问题,然后就很容易解决了。
本文有一些地方摘录了一下赵爽《2-SAT解法浅析》 (侵删)
一些概念
问题:就是给一些布尔变量赋值,使得所有给你的条件成立的问题---适定性(Satisfiability)问题。我们令为所有条件中含有变量的最大值,那么我们就可以称其为问题。
可以证明时候为NP完全问题,而的时候存在多项式解法。
问题 : 就是对于每一个条件,最多只于两个变量的真假性有关,网上大部分博客都列出来了那11种条件,本文不再赘述(并且觉得没啥必要...)
基本建图方式
作为引入,我们在这里简单讨论一下其中一种情况。
也就是为真或为真的情况。
我们从这里可以得到两种情况:
- 为假的时候,必为真;
- 为假的时候,必为真。
我们把原图每个拆成两个点,分别代表它为假和它为真。(习惯把他们标号为和。)
然后我们就可以得到和这两条边。
不难发现我们可以定义此处边的意义是“推导出” (来自刘汝佳的大白书)
对于其他的情况我们也都可以这样做。
例如:
- 必为真,那么就可以连一条的边;
- 为真时,为假,那么就有一条的边;
- 和状态要一样,和的边。
但我们常常不能只连一条边,因为这样会出错(后文会提到)。
我们就可以引入另外一条边(也就是逆否命题等价)。
这从这个名称可以大概看出这条边是什么意思。
逆否命题等价:
如果我们有的一个推导,那必定会有的另一个推导。
也就是具有前一条边,就一定会有后一条边。
这是为什么呢qwq 我们可以通过之前那个例子2来简单说明一下。
为真时,为假,那么就有一条的边
通过之前的定义,我们可以得到的边。
也就是说为真的时候,必为假。(这个显然是要成立的)
之前举的第一个例子 强制使一个为真的状态 似乎就是两条边是一样的
所以整个图是个比较对称的一个图。
解法
有了上面那个图我们就很好办了!
如果我们会从为真时候的状态推导出为假的状态,那么肯定是不成立的。同样从假推到真也不行。
这个就是2-SAT不成立时候的情况。
那么我们先介绍一下解法一:
解法一:DFS枚举
我们首先枚举每个点的状态,真或者假(如果它之前没被标过)。然后将它能标记状态的全都标记一遍,
途中如果碰到自己这个状态已经被标记就返回真,如果反状态被标记了就返回假。
如果本状态当前假设状态不行,我们将它刚刚标出来的状态全部清空掉(用个栈来实现),
然后继续尝试它的一个反状态,如果反状态还是不行,那就是无解。
本算法没有回溯过程(可以yy一下证明。。。qwq)
最多尝试个点,每次要最多尝试条边,所以总复杂度是的。
(一开始我不相信这个复杂度...然后直到我碰到了真正的强数据...QAQ)
但其实它的表现是很优秀的,随机数据能很快的构造出解,并且比较好写,而且能求字典序最小的解。
还有一点,如果不连上之前的那个逆反命题等价,就会导致整个出错,就是你无法从后面状态反推回去原来的状态,然后就会导致一些本来可以成立的无法成立了。
ps : 我一开始错了,但顺着跑一遍,反着再跑一遍,似乎就可以了(也许是因为图是对称的?)
这个输出直接用mark
数组就行了,很简单。
代码实现
解法二:Tarjan缩点+拓扑序
这个就是将原图用Tarjan缩点,然后再进行判断的。(对于缩点,参考我这篇博客【模板】缩点)
其实那篇只讲了代码实现,并没有讲为啥那样做,其实我也不知道
如果对于一个点的两个状态真或假都在一个强联通分量(scc)中,那么肯定不成立。
我们可以用之前的那个DFS来配合理解,就是真能推导假,假也能推导到真,所以都不成立。
然后我们可以用拓扑序来染色求解,对于一个并未染色的点我们将它染成,它的一个对立状态染成。(此处应该是 反向拓扑 )
然后不断重复。最后所有为的就可以当做一组解了。
这个成立时因为,每个条件都是两两关系,只要保证了存在解,那么你这样绝对是可行的
(也可以理解为一连串的推导了)证明还是看那篇论文吧。。。
但写个拓扑序有点麻烦了。。我们可以利用Tarjan的一个性质,就是它的访问其实是根据拓扑序来的。
所以最后给他的scc标号(sccno
)正好和拓扑序相反。
如果对于一个sccno
比它的反状态的sccno
要小,那么我们用这个状态当做答案,否则用它的反状态当做答案。
也就是我们用 sccno
小的状态当做答案。
代码实现
例题讲解
LA 3211(模板)
题意
给你一些飞机停靠的时间(每台飞机共两个时刻,早和晚)问你两个相邻飞机最小停靠间隔的最大值。
题解
模板题qwq 这种最小最大二分答案最好啦,然后用2-SAT去check一下。 (早为真,晚为假。然后两个状态无法共存的就连两条推导的边)
好像这个东西可以用线段树优化(h10的考试题)但我不会啊!!
LA 3713
题意
给你一些宇航员,按小于平均年龄和大于等于平均年龄分为两组,小于的只能执行和任务,大于等于的只能执行和任务。然后告诉你一些二元关系,就是代表哪对人不能分到同一组。问是否存在解,存在的话输出方案。
题解
虽然有三个任务,但每个人也是只有两个状态,也可以用2-SAT直接解决。也是不能共存的那种连边,手动模拟一下就好了。
ps : DFS可以直接过本题()的数据.... 这就是我怀疑复杂度的起源...
【NOI2017】游戏
题意
见链接。。不想再写了。。
题解
NOI真题模拟!!!好像是第一次考2-SAT?
看我另外一篇博客题解就行咯qwq [UOJ317]【NOI2017】游戏 题解....
__EOF__

本文链接:https://www.cnblogs.com/zjp-shadow/p/8596760.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角【推荐】一下。您的鼓励是博主的最大动力!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效