部分轉自https://blog.csdn.net/jarjingx/article/details/8521690
博主講的真的太棒了
2-sat
定義:
有一些集合,每個集合裏面有且僅有兩個元素,且不能同時選取兩個元素,集合間的元素存在一定的選擇關係,求解可行解以及可行方案
// 如果元素最多的集合裏面有k個元素,則稱其爲k-sat問題,可以證明是NP完全問題(出門右轉百度百科)
方法:
1.連邊
2.tarjan縮點,連反邊
3.判斷可行性,即同一集合中的兩點是否屬於一個強聯通分量
4.拓撲排序,若當前節點沒有被訪問過,則選擇該點,不選擇其他的點
5.構造方案
連邊
算法本身並不難,關鍵在於連邊,充分理解好邊的概念:a->b表示選a必選b
a,b不能同時取 :a->b',b->a'
a,b不能同時不取 :a'->b,b'->a
a,b要麼都取要麼都不取 :a->b,b->a,a'->b',b'->a'
a,b必須同時取 :同上
a必須取 :a->a'
縮點
tarjan縮點,將所有邊反過來
#以下將強聯通分量簡稱爲分量
判斷可行性
枚舉每個集合,判斷其兩個元素是否在同一個分量內,若在同一個內則不可行
拓撲排序
將縮點後的分量進行排序
構造方案
按照拓撲後的順序依次訪問所有分量,若某個分量沒有被訪問則將其標記爲"選擇",不傳遞"選擇"標記,將被選分量的對立分量標記爲"不選擇",將其"不選擇"的標記沿着傳遞(注意邊已經反過來了)