只有2 SAT不是NPC呢 2 SAT學習筆記

2022-05-26 07:54:07 字數 3486 閱讀 3132

\[}\]

我們舉乙個簡單的例子:

機房裡有三位大佬小s,小l,小m和乙個蒟蒻tqr,他們刷題時有不同的要求(因為蒟蒻什麼題都不會做,故不列舉):

大佬/要求

小s小l

小m 要求1

不包含數論知識(¬a)

包含數論知識(a)

不包含數論知識(¬a)

要求2包含幾何知識(b)

包含幾何知識(b)

不包含幾何知識(¬b)

要求3不包含圖論知識(¬c)

不包含圖論知識(¬c)

包含圖論知識(c)

在此之前,複習一下前置數學知識:

對於乙個命題:如果a,那麼b

其逆命題為:如果b,那麼a

其否命題為:如果¬a,那麼¬b

其逆否命題為:如果¬b,那麼¬a

∧表示與,∨表示或,¬表示非

原命題與逆否命題等值。逆命題與否命題等值

原命題與逆命題以及逆否命題與否命題之間沒有關係

我們繼續上面的情景,如果我們要出一道題,使這道題能同時滿足上面三位dalao的喜好,該如何做?

經過數學分析,滿足的題目一定符合以下條件(¬a∨b∨¬c)∧(a∨b∨¬c)∧(¬a∨¬b∨c)

因此我們要做的就是給每個變數賦值,使上式值為true

是的,這就是sat問題,但需要注意的是,上面的情況中,每個同學對題目都有三個限制,因此是3-sat問題

可證明的,3(及以上)-sat問題都是npc問題(即不可使用演算法解決,唯一的方法是暴力列舉)

因此,2-sat問題是演算法能解決的極限,那麼我們將限制改一改:

經過一段時間的學習後,除了tqr,其他人都完全掌握了圖論知識……

一波操作過後,限制條件變成了(¬a∨b)∧(a∨b)∧(¬a∨¬b),這就是我們要學習的2-sat了

那我們就開始吧……

首先,我們需要將幾個互相有限制的點賦值,那就把它們丟到圖裡面!

建立兩個點,分別是a和¬a(儲存時,可以存到編號分別為 \(i\) 和 \(i+maxn\) 的節點上,就像並查集對稱點一樣)

那麼每個點之間的關係是什麼?

(a∨b)可以理解為若a為真,則b為假,反之b為真

於是我們可以建出圖形:

由圖形可以發現,a與¬b,以及¬a與b都在同乙個強連通分量裡,於是我們可以得出結論:

2-sat問題同乙個強連通分量中的所有元素值相同

很顯然的,如果a與¬a(或者x與¬x,x代表任意條件)在同乙個強連通分量裡,即他們的值相等,那麼出現了矛盾,可判斷問題無解(就像1=-1一樣,矛盾的等式)

有n個布林變數 \(x_1\)~\(x_n\),另有 \(m\) 個需要滿足的條件,每個條件的形式都是 \(x_i\)為true/false或 \(x_j\)為true/false。你的mubiao給每個變數賦值使得所有條件得到滿足。

第一行兩個整數\(n\)和\(m\),意義如題面所述

接下來\(m\)行每行\(4\)個整數\(i,a,j,b\),表示\(x_i\)為\(a\)或\(x_j\)為\(b\)」\((a,b∈\)\)

如無解,輸出\(impossible\);否則輸出\(possible\),

下一行\(n\)個整數\(x_1\)~\(x_n\)

\((x_i∈\)\),表示構造出的解。

很顯然地,我們需要按照上述所說的來建邊

read(n);read(m);

for(register int i=1;i<=m;++i)

然後tarjan找強連通分量(color陣列是拓撲序)

void tarjan(int u)

else if(vis[v]) low[u]=min(low[u],dfn[v]);

} if(dfn[u]==low[u]) }

}for(register int i=1;i<=2*n;++i) if(!dfn[i]) tarjan(i);

如果強連通分量 \(x_0\), \(x_1\) 在縮點後 \(dag\) 的底圖中連通,那麼我們選擇的一定是拓撲序較大的

\(tarjan\) 求強連通分量得到的強連通分量編號是遵循拓撲序逆序的,所以如果 \(x_0\) 的編號更小,輸出 \(0\),否則輸出 \(1\)

for(register int i=1;i<=n;++i)

if(color[i]==color[i+n])

puts("possible");

for(register int i=1;i<=n;++i)

printf(color[i]>color[i+n]?"1 ":"0 ");

這道題就很輕鬆地解決了,下面是完整**

#includeusing namespace std;

int n,m,a,va,b,vb;

struct edge

edge[2000005];

int cnt=0,head[2000005];

inline void add_edge(int from,int to)

int low[2000005],dfn[2000005],color[2000005],tms,idx;

bool vis[2000005];

stacksta;

void tarjan(int u)

else if(vis[v]) low[u]=min(low[u],dfn[v]);

} if(dfn[u]==low[u]) }

}templateinline void read(t &res)

int main()

for(register int i=1;i<=2*n;++i) if(!dfn[i]) tarjan(i);

for(register int i=1;i<=n;++i)

if(color[i]==color[i+n])

puts("possible");

for(register int i=1;i<=n;++i)

printf(color[i]>color[i+n]?"1 ":"0 ");

return 0;

}

有什麼不懂的可以發qq問我,沒了

模板 2 SAT 問題 2 SAT

2 sat 問題 模板 有n個布林變數 x 1 x n 另有m個需要滿足的條件,每個條件的形式都是 x i 為true false或 x j 為true false 比如 x 1 為真或 x 3 為假 x 7 為假或 x 2 為假 2 sat 問題的目標是給每個變數賦值使得所有條件得到滿足。輸入格式...

2 SAT學習筆記

由對稱性解2 sat問題 2 sat解法 上面兩篇 很清楚的介紹了什麼是2 sat以及一些原理演算法 2 sat問題是圖論中乙個比較有意思的問題,重點是建圖,對於邊的意思,就是如果你選了i,就必須選j。2 sat問題有個很明顯的地方就是對於每個i,i包含兩個點,i表示選第乙個點,i 表示選第二個點,...

2 SAT學習總結

2 sat 圖論演算法 理解 給定乙個布林方程,判斷是否存在一組布林變數的取值方案,使得整個方程值為真的問題,被稱為布林方程的可滿足性問題 sat sat 問題是 np 完全的,但對於一些特殊形式的 sat 問題我們可以有效求解。我們將下面這種布林方程稱為合取正規化 其中稱為文字,它是乙個布林變數或...