2-SAT问题
-(-1).前置知识
-
逻辑运算符及逻辑运算规则
-
拓扑序和拓扑排序
-
tarjan算法与有向图的连通性(强连通分量)
-1.SAT 问题及 2-SAT 问题的定义
SAT 问题,全称为 Satisfiability 问题,中文翻译为可满足性问题,一般形式为 k-可满足性问题,简称 k-SAT 问题。
给定 \(n\) 个 \(bool\) 变量,有 \(m\) 组 \(bool\) 方程,为这些变量的取值限制,求是否存在 \(n\) 个变量的合法赋值,使得 \(n\) 个变量满足 \(m\) 组取值限制。这就是 SAT 问题。
当每个 \(bool\) 方程中描述的 \(bool\) 变量的个数 \(k\) 大于 \(2\) 时,SAT问题被证明为一个 NPC 问题,因此无法在多项式复杂度内解决。
2-SAT 问题就是SAT问题中 \(k = 2\) 的情况。这种情况可以转化为图论问题,继而在多项式复杂度内解决。该算法由 Aspvall、Plass 和 Tarjan 在 1979 年提出。
举个例子
XX教练收了五个学生,每个学生都学过OI,码风也都不相同。现在XX教练需要写一份每个学生看了都顺眼的代码,也就是满足每个人的码风其中一个习惯。XX教练很懒,所以来问你。每个人的码风如下:
-
第一个人
-
1.宏定义long long
-
2.压行
-
-
第二个人
-
1.大括号不单独用一行
-
2.用万能头
-
-
第三个人
-
1.宏定义long long
-
2.不用万能头
-
-
第四个人
-
1.大括号单独用一行
-
2.不压行
-
-
第五个人
-
1.不压行
-
2.不用万能头
-
我们不难发现,宏定义long long、不压行、大括号不单独用一行就是一组合法的解,并且解不限于此。
-2.2-SAT问题的解法
我们分析一下上一个部分的例子。
一共有四种习惯,分别是宏定义long long、压行、大括号单独用一行、用万能头。我们可以把它们看作四个变量 \(a_1\)、\(a_2\)、\(a_3\)、\(a_4\)。由于每种习惯都只有两种状态:用或者不用,所以这些变量我们都可以看作是 \(bool\) 类型的,变量前加 \(\neg\) 表示对当前要求表示否定。
五个约束条件可以表示成一个 \(bool\) 方程 \((a_1\lor{a_2})\land(\neg{a_3}\lor{a_4})\land(a_1\lor\neg{a_4})\land(a_3\lor\neg{a_2})\land(\neg{a_2}\lor\neg{a_4})\)。
观察一下这些约束条件。我们拿第一个约束条件为例,宏定义long long或压行。我们稍微修改一下,如果我们不宏定义long long的话,那是不是就必须压行了呢?抽象一点,如果一个条件 \(a_i\) 不成立,那么另一个条件 \(a_j\) 就必须成立。这里面就带有了一种指向性(\(\neg{a_i} \to a_j\))。
于是我们可以将指向性转化为一条有向边,由 \(x\) 指向 \(y\),表示若 \(x\) 成立,则 \(y\) 一定成立。
把 \(a_i\) 按照状态 \(0\) 和 \(1\) 拆分成两个点,状态 \(1\) 表示为点 \(i\),状态 \(0\) 表示为点 \(i + n\)(\(a_i\) 为 \(bool\) 变量,\(n\) 为变量个数)。
我们继续来看上面那个例子,将它按照这种规则建好的图是这样的
如果有一个变量的两种状态 \(i\) 和 \(i + n\) 能够互相到达(存在从 \(i\) 到 \(i + n\) 的路径也存在 \(i + n\) 到 \(i\) 的路径),那么 \(i\) 和 \(i + n\) 就是矛盾的(既要选一种状态又要选另一种状态)。也就是说,如果 \(i\) 和 \(i + n\) 存在于同一个强连通分量中,那么 \(i\) 和 \(i + n\) 就矛盾,此问题无解。