例:
struct twosat
//x=xval or y=yval
void
add_clause
(int x,
int xv,
int y,
int yv)
void
init
(int n)
bool
solve()
}return1;}};
為什麼不需要回溯呢?
因為以前定下的變數如果在一輪dfs完之後沒有判為無解,那麼以後新確定的變數就不會影響到它,不會因為它而無解。
由於連邊的雙向性(有(x,
y)(x,y)
(x,y
)必有(y′
,x′)
(y',x')
(y′,x′
)),如果以前有個變數確定為了x
xx,dfs完之後i
ii和i′i'
i′都沒有被選,現在我們確定i
ii,順著dfs確定過去是不可能找到x′x'
x′的,如果那樣的話,x
xx在dfs中必然可以找到i
ii。所以一輪dfs就確定了一系列點集,其它沒有確定的變數就不會訪問到它們了。
這個演算法的最壞複雜度是o(n
m)o(nm)
o(nm
)的,一般達不到,好處是可以輸出字典序最小的方案。
更常使用的是tarjan縮點求一組可行解,複雜度為o(m
)o(m)
o(m)
,如果縮點後不存在x
xx和x′x'
x′在同乙個強聯通分量內則必定有解,並可以通過拓撲排序求解(其實拓撲序就是強聯通分量的編號反過來,直接選擇所在強聯通分量編號小的點即可)。
關於這種演算法的具體過程以及原理的證明分析可以看《由對稱性解2-sat問題》,很好地解釋了為什麼一定有解,以及構造解的正確性,對圖的對稱性有非常充分的解讀。
2 SAT學習筆記
由對稱性解2 sat問題 2 sat解法 上面兩篇 很清楚的介紹了什麼是2 sat以及一些原理演算法 2 sat問題是圖論中乙個比較有意思的問題,重點是建圖,對於邊的意思,就是如果你選了i,就必須選j。2 sat問題有個很明顯的地方就是對於每個i,i包含兩個點,i表示選第乙個點,i 表示選第二個點,...
2 SAT學習筆記
2 sat問題指的是,給你若干個0 1變數。並給你一些限制,讓你求滿足這些限制的可行解 字典序最小的解 限制的種類包括以下幾種 1 a一定是1 2 a一定不是1 3 a,b至少有1個是1 4 a,b最多有乙個是1 5 a,b一定相同 6 a,b一定不同 一般思路是對於乙個變數,建立兩個變數 正,反 ...
學習筆記 2 SAT
拆點 將每個 bool 變數拆成 0,1 兩個點.連邊 將限制條件轉化為連邊.圖是 dag 時,對於每個 bool 變數,合法點的拓撲序大於非法點.證明 若某個 bool 變數拆分成的兩個點為 u,v 若 u 為非法點,則存在一條從 u 到 v 的路徑,所以 v 的拓撲序一定大於 u 的拓撲序.當圖...