2-SAT 学习笔记
2-SAT 问题模型:构造 bool
变量 \(x_1,x_2...x_n\),使得满足一些限制一对 \(x_1\) 和 \(x_2\) 取值的条件合法。
很显然根据 Floyd
传递闭包可以做到 \(O(n^3+m)\),但不太行。
有 \(O(n+m)\) 的做法,发现对于每个条件是要我们选择一种取值(选择就很缥缈),我们考虑转换为一些定性的限制条件(更为直接一些)。
因为每个点只有两种取值,所以对每个限制考虑分类讨论,拿 \(x_7\) 为假或 \(x_2\) 为假举例。
如果 \(x_7\) 取假,那么对 \(x_2\) 没有限制。如果 \(x_7\) 取真,那么 \(x_2\) 就必须取假。所以把他转换到图论模型,对 \(x_2\) 和 \(¬x_7\) 连边。同理,对 \(x_7\) 和 \(¬x_2\) 连边,边的含义就是如果取了 \(u\),那就必须取 \(v\)。
考虑无解的情况,很显然,如果一个 \(x_i\) 我们钦定它是 \(1\),但是发现推了一圈回来以后发现是 \(0\),那就产生了矛盾,那说明 \(x_i=1\) 是不可取的。
回到我们建出来的图上,实际就是如果 \(x_i\) 可以走到 \(¬x_i\) 且 \(¬x_i\) 能走到 \(x_i\) 那就是无解。
容易发现,他们是在一个强连通分量里面的,因为他们可以互相抵达。
所以我们只用对建出来的图跑一个缩点即可,如果 \(x_i\) 和 \(¬x_i\) 在一个强连通分量里面,那必然无解。
那考虑有解的情况的构造。
缩完了点以后,我们发现,拓扑序小的点一定是可以一层一层往里面推出来拓扑序大的点的答案,反之不行。
原因是如果你选择了拓扑序大的话,拓扑序小的点所在的那个环,其实就不能被更新到了。
但是 Tarjan
搞出来的拓扑序恰好的倒序的,因为他是个 dfs
,是自下而上的找到 SCC
,所以标号大的才是拓扑序小的点。
具体实现是要开 \(2n\) 个点来表示 \(0/1\) 的取值。
如果是 \(a \oplus b\),那显然是如果 \(a\) 取了 \(1\),\(b\) 只能取 \(0\),显然 \(a\) 和 \(¬b\) 连边, \(b\) 和 \(¬a\) 连边。
如果是 $a \land b $,如果 \(a\) 取了 \(0\),必然矛盾,所以 \(¬a\) 和 \(a\) 连边直接让他矛盾掉。
在实际问题里面,可以转换成一个点的选/不选成为 \(0/1\) 的变量,单独对每个点和每个限制考虑,这是两种不一样的思路。
标签:序小,连边,拓扑,笔记,学习,如果,取值,SAT From: https://www.cnblogs.com/JuneFailue/p/18118170