2-SAT适定性(Satisfiability)问题知识点详解
SAT是適定性(Satisfiability)問題的簡稱。一般形式為k-適定性問題,簡稱 k-SAT。而當k>2時該問題為NP完全的,所以我們只研究k=2時情況。
2-SAT問題
現有一個由N個布爾值組成的序列A,給出一些限制關系,比如A[x] AND A[y]=0、A[x] OR A[y] OR A[z]=1等,要確定A[0…N-1]的值,使得其滿足所有限制關系。這個稱為SAT問題,特別的,若每種限制關系中最多只對兩個元素進行限制,則稱為2-SAT問題。通俗來說就是有一些集合,每個集合中有且僅有兩個元素,且不能同時選取兩個元素,集合間的元素存在一定的選擇關系,求解可行性及可行方案。
由于在2-SAT問題中,最多只對兩個元素進行限制,所以可能的限制關系共有11種:
注意:
這里的OR是指兩個條件至少有一個是正確的
比如x1和x2一共有三種組合滿足“x1為真或x2為假”:
x1=1,x2=1
x1=1,x2=0
x1=0,x2=0
A[x]
NOT A[x]
A[x] AND A[y]
A[x] AND NOT A[y]
A[x] OR A[y]
A[x] OR NOT A[y]
NOT (A[x] AND A[y])
NOT (A[x] OR A[y])
A[x] XOR A[y]
NOT (A[x] XOR A[y])
A[x] XOR NOT A[y]
進一步,A[x] AND A[y]相當于(A[x]) AND (A[y])(也就是可以拆分成A[x]與A[y]兩個限制關系),NOT(A[x] OR A[y])相當于NOT A[x] AND NOT A[y](也就是可以拆分成NOT A[x]與NOT A[y]兩個限制關系)。因此,可能的限制關系最多只有9種。
首先我們考慮將2-SAT問題往圖論的方向靠,我們發現每個點要么取0,要么取1。因此對于ai,我們建兩個點2i?1與2i分別表示ai取0和1
然后我們考慮建邊來表示這些關系,我們令一條有向邊的意義:x→y表示如果選擇了x就必須選y
那么我們可以舉一些簡單的例子來總結下連邊的規律(用i′表示i的反面):
i,j不能同時選:選了i就要選j′,選j就要選i′。故i→j′,j→i′。一般操作即為aixoraj=1
i,j必須同時選:選了i就要選j,選j就要選i。故i→j,j→i。一般操作即為aixoraj=0
i,j任選(但至少選一個)選一個:選了i就要選j′,選j就要選i′,選i′就要選j,選j′就要選i。故i→j′,j→i′,i′→j,j′→i。一般操作即為aioraj=1
i必須選:直接i′→i,可以保證無論怎樣都選i。一般操作為給出的ai=1或aiandaj=1
建好圖然后就是考慮怎么用圖論的方式解決2-SAT了。
在實際問題中,2-SAT問題在大多數時候表現成以下形式:有N對物品,每對物品中必須選取一個,也只能選取一個,并且它們之間存在某些限制關系(如某兩個物品不能都選,某兩個物品不能都不選,某兩個物品必須且只能選一個,某個物品必選)等,這時,可以將每對物品當成一個布爾值(選取第一個物品相當于0,選取第二個相當于1),如果所有的限制關系最多只對兩個物品進行限制,則它們都可以轉化成9種基本限制關系,從而轉化為2-SAT模型。
【建模】
其實2-SAT問題的建模是和實際問題非常相似的。
建立一個2N階的有向圖,其中的點分為N對,每對點表示布爾序列A的一個元素的0、1取值(以下將代表A[i]的0取值的點稱為i,代表A[i]的1取值的點稱為i’)。顯然每對點必須且只能選取一個。然后,圖中的邊具有特定含義。若圖中存在邊<i, j>,則表示若選了i必須選j。可以發現,上面的9種限制關系中,后7種二元限制關系都可以用連邊實現,比如NOT(A[x] AND A[y])需要連兩條邊<x, y’>和<y, x’>,A[x] OR A[y]需要連兩條邊<x’, y>和<y’, x>。而前兩種一元關系,對于A[x](即x必選),可以通過連邊<x’, x>來實現,而NOT A[x](即x不能選),可以通過連邊<x, x’>來實現。
【O(NM)算法:求字典序最小的解】
算法 1、連邊
2、跑tarjan
3、判可行性,即同一集合中的兩個點是否同屬一個強連通塊
4、縮點建新圖,連反邊
5、拓撲序,若當前點沒有被訪問過,則選擇該點,不選擇其另外的點
連邊 2-SAT算法本身并不難,關鍵是連邊,不過只需要充分理解好邊的概念:a->b即選a必選b。
a、b不能同時選:選了a就要選b’,選了b就要選a’。
a、b必須同時選:選了a就要選b,選了b就要選a,選了a’就要選b’,選了b’就要選a’。
a、b必須選一個:選了a就要選b’,選了b就要選a’,選了a’就要選b,選了b’就要選a。
※a必須選:a’->a。
根據2-SAT建成的圖中邊的定義可以發現,若圖中i到j有路徑,則若i選,則j也要選;或者說,若j不選,則i也不能選;
因此得到一個很直觀的算法:
(1)給每個點設置一個狀態V,V=0表示未確定,V=1表示確定選取,V=2表示確定不選取。稱一個點是已確定的當且僅當其V值非0。設立兩個隊列Q1和Q2,分別存放本次嘗試選取的點的編號和嘗試不選的點的編號。
(2)若圖中所有的點均已確定,則找到一組解,結束,否則,將Q1、Q2清空,并任選一個未確定的點i,將i加入隊列Q1,將i’加入隊列Q2;
(3)找到i的所有后繼。對于后繼j,若j未確定,則將j加入隊列Q1;若j’(這里的j’是指與j在同一對的另一個點)未確定,則將j’加入隊列Q2;
(4)遍歷Q2中的每個點,找到該點的所有前趨(這里需要先建一個補圖),若該前趨未確定,則將其加入隊列Q2;
(5)在(3)(4)步操作中,出現以下情況之一,則本次嘗試失敗,否則本次嘗試成功:
<1>某個已被加入隊列Q1的點被加入隊列Q2;
<2>某個已被加入隊列Q2的點被加入隊列Q1;
<3>某個j的狀態為2;
<4>某個i’或j’的狀態為1或某個i’或j’的前趨的狀態為1;
(6)若本次嘗試成功,則將Q1中的所有點的狀態改為1,將Q2中所有點的狀態改為2,轉(2),否則嘗試點i’,若仍失敗則問題無解。
該算法的時間復雜度為O(NM)(最壞情況下要嘗試所有的點,每次嘗試要遍歷所有的邊),但是在多數情況下,遠遠達不到這個上界。
具體實現時,可以用一個數組vst來表示隊列Q1和Q2。設立兩個標志變量i1和i2(要求對于不同的i,i1和i2均不同,這樣可以避免每次嘗試都要初始化一次,節省時間),若vst[i]=i1則表示i已被加入Q1,若vst[i]=i2則表示i已被加入Q2。不過Q1和Q2仍然是要設立的,因為遍歷(BFS)的時候需要隊列,為了防止重復遍歷,加入Q1(或Q2)中的點的vst值必然不等于i1(或i2)。中間一旦發生矛盾,立即中止嘗試,宣告失敗。
該算法雖然在多數情況下時間復雜度到不了O(NM),但是綜合性能仍然不如下面的O(M)算法。不過,該算法有一個很重要的用處:求字典序最小的解!
如果原圖中的同一對點編號都是連續的(01、23、45……)則可以依次嘗試第0對、第1對……點,每對點中先嘗試編號小的,若失敗再嘗試編號大的。這樣一定能求出字典序最小的解(如果有解的話),因為一個點一旦被確定,則不可更改。
如果原圖中的同一對點編號不連續(比如03、25、14……)則按照該對點中編號小的點的編號遞增順序將每對點排序,然后依次掃描排序后的每對點,先嘗試其編號小的點,若成功則將這個點選上,否則嘗試編號大的點,若成功則選上,否則(都失敗)無解。
推薦博客
1> https://blog.csdn.net/jarjingx/article/details/8521690
2> https://www.cnblogs.com/kangkang-/p/11370313.html
總結
以上是生活随笔為你收集整理的2-SAT适定性(Satisfiability)问题知识点详解的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: HDU 3062 Party(2-sat
- 下一篇: Dreamoon and Ranking