有 \(n\) 個布林變數 \(x_1\)
\(\sim\)
\(x_n\),另有 \(m\) 個需要滿足的條件,每個條件的形式都是 「\(x_i\) 為true
/false
或 \(x_j\) 為true
/false
」。比如 「\(x_1\) 為真或 \(x_3\) 為假」、「\(x_7\) 為假或 \(x_2\) 為假」。
2-sat 問題的目標是給每個變數賦值使得所有條件得到滿足。
對於乙個要求 「\(x\) 為true
或 \(y\) 為true
」,它的意思就是 「如果 \(x\) 為false
那麼 \(y\) 必須是true
,如果 \(y\) 為false
那麼 \(x\) 必須是false
」。
把每個點拆成true
和false
兩個點。在上例中,我們就從 \(x_f\) 向 \(y_t\) 連邊,\(y_f\) 向 \(x_t\) 連邊。
那麼如果若干個點在乙個強連通分量內,那麼他們的取值是一樣的。
所以 tarjan 縮點,記錄每乙個點屬於哪乙個強連通分量 \(col[x]\),顯然如果 \(col[x_t]=col[x_f]\),那麼無解。
#include #include #include #include using namespace std;
const int n=2000010;
int n,m,cnt,tot,head[n],dfn[n],low[n],col[n];
bool vis[n];
stackst;
struct edge
e[n*2];
void add(int from,int to)
void tarjan(int x)
else if (vis[v])
low[x]=min(low[x],dfn[v]);
} if (dfn[x]==low[x])
while (x!=y); }}
int main()
tot=0;
for (int i=1;i<=n*2;i++)
if (!dfn[i]) tarjan(i);
for (int i=1;i<=n;i++)
if (col[i]==col[i+n]) return printf("impossible"),0;
printf("possible\n");
for (int i=1;i<=n;i++)
if (col[i]>col[i+n]) printf("1 ");
else printf("0 ");
return 0;
}
洛谷 P4782 模板 2 SAT 問題
2 sat問題可以通過強連通分量來判斷條件是否矛盾。而題目往往會要求輸出方案,輸出方案時,強連通分量的scc值,會和原圖的拓撲序緊密聯絡在一起。include using namespace std const int n 1e6 5 int n,m,a,b,nowa,nowb int cnt,he...
P4782 模板 2 SAT 問題
傳送門 2 sat的板子 把每乙個點拆成選0或選1 條件為 x i 為 a 或 x j 為 b 那麼如果 x i 不為 a 則 x j 必為 b 同理 x j 不為 b 則 x i 必為 a 那麼從 x i 不為 a 的點向 x j 為 b 的點連邊,從 x j 不為 b 的點向 x i 為 a 的...
《P4782 模板 2 SAT 問題》
2 sat問題 就是一些元素,他們的值只能為布林值0,1.給出一些限制關係,並且每對關係都是兩個數之間的。讓你找出一組構造,讓所有關係都滿足。解法 首先要建圖 我們規定,a為1的點為a n,a為0的點為a。那麼對於給定的一對關係a b。如果是a 1,b 1,那麼說明a b。利用可以轉化為 a b,b...