生活随笔
收集整理的這篇文章主要介紹了
2-SAT
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
2-Satisfiability
2可滿足性,2-SAT或僅2SAT是將值賦值給變量的計算問題,每個變量具有兩個可能的值,以滿足變量對的約束系統。這是一般布爾可滿足性問題的一個特例,它可能涉及對兩個以上變量的約束,以及約束滿足問題,這可以允許對每個變量的值進行兩次以上的選擇。但與NP完全的那些更一般的問題形成對比,可以在多項式時間內求解2-可滿足性。
個人理解
多個約束條件每個約束有兩個限制,判斷是否存在滿足所有條件的合理解
思路
對于這樣的一組限制 AAA和BBB不能同時存在,我們可以轉化成滿足AAA的條件下BBB就不能滿足,對應建圖的時候我們把每個點拆成兩個情況選or不選,根據情況建邊
1.是否存在解
hihoCoder #1467
Tarjan縮點,如果一個強連通分量里面存在矛盾(一個點選和不選同時存在)就不存在解
2.求一個字典序最小的解
hihoCoder #1468
暴力DFS O(NMNMNM)
首先SAT建邊,然后對于每個點先從小的序號DFS,之后判斷標記的點中是否存在矛盾,如果拆成的兩個點都存在矛盾,那就無解
vector
<int> g
[maxn
];
int vis
[maxn
], temp
[maxn
], len
;int other(int x
) {return (x
& 1) ? x
+1 : x
-1;
}int dfs(int x
) {if (vis
[other(x
)]) return 0;if (vis
[x
]) return 1;temp
[len
++] = x
;vis
[x
] = 1;for (int i
= 0, y
; i
< (int)g
[x
].size(); ++i
) {y
= g
[x
][i
];if (dfs(y
) == 0) return 0;}return 1;
}int Twosat() {for (int i
= 1; i
<= n
; ++i
) {if (vis
[i
*2] || vis
[i
*2-1]) continue;if (dfs(i
*2-1) == 0) {for (int j
= 0; j
< len
; ++j
) {vis
[temp
[j
]] = 0;}len
= 0;if (dfs(i
*2) == 0) {return 0;}}}return 1;
}if (Twosat()) {for (int i
= 1; i
<= n
; ++i
) {if (vis
[i
*2-1]) cout
<< "R";else cout
<< "B";}cout
<< endl
;
}else cout
<< -1 << endl
;
總結
以上是生活随笔為你收集整理的2-SAT的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。