洛谷P4782 模板 2 SAT 問題

2022-06-13 22:36:11 字數 1440 閱讀 2516

有 \(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」。

把每個點拆成truefalse兩個點。在上例中,我們就從 \(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...