2-SAT学习总结

来源:互联网 发布:淘宝千牛客服怎么设置 编辑:程序博客网 时间:2024/06/06 01:32

2-SAT 图论算法:

 

理解:

给定一个布尔方程,判断是否存在一组布尔变量的取值方案,使得整个方程值为真的问题,被称为布尔方程的可满足性问题(SAT)SAT 问题是NP 完全的,但对于一些特殊形式的SAT 问题我们可以有效求解。

我们将下面这种布尔方程称为合取范式:

 

其中称为文字,它是一个布尔变量或其否定。像这样用连接的部分称为子句。如果合取范式的每个子句中的文字个数都不超过两个,那么对应的SAT 问题又称为2-SAT 问题。

 

思想:

    对于给定的2-SAT ,首先将每个子句 (a || b) = 1 改写成等价形式(!a => b || !b => a) 我们可以简单的理解为,若a为不为真,则b一定为假。对于每个变量x, 构造两个顶点分别代表x, !x,用推出的关系为边建立有向图, 如果图中的a能到达b,则当a为真时,b一定为真。因此我们可以认为该图中同一个强连通分量中所含的所有变量的bool 值均相同。

若存在某个变量x, x 和 !x 的两个顶点在同一个强连通分量中,原bool 表达式的值就不能为真,反之,若没有这样的情况,我们可以进行强连通分量的缩点,构新图,显然,新图是一个dag(有向无环图,即拓扑图),我们求出它的一个拓扑序。那么对于每个变量x,存在。x所在的强连通分量(新图)的拓扑序在 !x 所在的强连通分量之后ó x为真。 这就是使得当前bool表达式成立的一组bool变量取值。

 

算法优化:

    如果有用心学tarjan, 你应该能够发现一点,其实

tarjan 求SCC 就是按照头拓扑序逆序来求的。

证明:其实具体的证明应该不是太简单,但是我有一个形象的说明方法,考虑这么一个问题,我们进行tarjan-dfs 时,我们是根据边的指向不断层数加深的,那么,我们先找到的一定是递归层数最深的,也就是拓扑序最大的了。所以事情就变得简单了许多,我们可以用 scc_id[u] < scc_id[v]ó top[u] > top[v] 来等价。

 

时间复杂度:

     若bool变量的个数为n, 子句个数为m, 那么用tarjan 求解的时间复杂度就是O(n + m)。

 

建图规则:

常见的2-SAT 建图中的bool子句一般就是用三种符号连接,&(and), |(or), ^(xor), 下面我们来分别讨论。

1、(a & b) = true

ð a = true, b = true (强制为true)

ð !a -> a, !b -> b

解释:显然我们要强制要求a, b 均为true, 所以如果我们想达成这个目的我们就需要在即使选中!a 为真的情况下,也要让a 为真,所以直接!a -> a( 由!a 到a 连边, 表示当!a = trueè a = true)。

 

2、(a & b) = false

ð a = false or b = false or a, b = false

ð a = true -> b = false, b = true -> a = false

ð a -> !b, b -> !a

解释:显然我们要强制要求a, b 中有一个为false, 也就是说选择了一个为true 后, 另一个一定为false, 所以由 a -> !b, b -> !a 连边。

 

3、(a | b) = true

ð a = true or b = true or a, b = true

ð a = false -> b = true, b = false -> a = true

ð !a -> b, !b -> a

解释:显然我们要强制要求a, b 中有一个为true, 也就是说选择了一个为flase 后, 另一个一定为true, 所以由 !a -> b, !b -> a 连边。

 

4、(a | b) = false

ð a = false ans b = false (强制为false)

ð a -> !a, b -> !b

解释:显然因为我们要强制要求a, b 均为false, 所以如果我们想达成这个目的我们就需要在即使选中a为真的情况下,也要让!a为真,所以直接a -> !a( 由a 到!a 连边, 表示当a = trueè !a = true)。

 

5、(a ^ b) = true

ð a != b

ð a = true -> b = false, a = false -> b = true, b = true -> a = false, b = false -> a = true

ð a -> !b, !a -> b, b -> !a, !b -> a

解释:显然我们要强制要求a, b 不相同, 所以如果我们想达成这个目的我们就需要其中一个确定之后,确定另一个与它相反,所以直接a -> !b, !a -> b, b -> !a, !b -> a 连边即可。

 

6、(a ^ b) = false

ð a == b

ð a = true -> b = true, a = false -> b = false, b = true -> a = true, b = false -> a = false

ð a -> b, b -> a, !a -> !b, !b -> !a

解释:显然我们要强制要求a, b 相同, 所以如果我们想达成这个目的我们就需要其中一个确定之后,确定另一个与它相同,所以直接!a -> !b, a -> b, !b -> !a, b -> a 连边即可。

 

适用例题:

poj 3678

题目大意 : 给出一堆bool 表达式, 询问是否有满足全部的可行解,有就输出YES ,没有就输出NO 。

分析:显然这就是一道2-SAT 裸题(毫不掩饰),直接上就好,只不过呢,这道题有一个好处就是可以锻炼建图。

Source:

 

 

 

 

 

0 0
原创粉丝点击