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 裸題(毫不掩飾),直接上就好,只不過呢,這道題有乙個好處就是可以鍛鍊建圖。
模板 2 SAT 問題 2 SAT
2 sat 問題 模板 有n個布林變數 x 1 x n 另有m個需要滿足的條件,每個條件的形式都是 x i 為true false或 x j 為true false 比如 x 1 為真或 x 3 為假 x 7 為假或 x 2 為假 2 sat 問題的目標是給每個變數賦值使得所有條件得到滿足。輸入格式...
2 SAT學習筆記
由對稱性解2 sat問題 2 sat解法 上面兩篇 很清楚的介紹了什麼是2 sat以及一些原理演算法 2 sat問題是圖論中乙個比較有意思的問題,重點是建圖,對於邊的意思,就是如果你選了i,就必須選j。2 sat問題有個很明顯的地方就是對於每個i,i包含兩個點,i表示選第乙個點,i 表示選第二個點,...
2 SAT學習小記
推薦部落格 研究總結 2 sat問題 現在有n個集合,每個集合裡有一些元素。現在要求從每個集合裡選出乙個元素,並且兩兩集合選出的元素有限制 記乙個集合裡最多有k個元素,那麼這個問題稱作k sat問題。k 2即是2 sat問題,是有價值討論的問題。當k 3時,被證明是np完全問題,是無法在多項式複雜度...