模板 2 SAT 問題 2 SAT

2022-04-29 22:15:15 字數 1889 閱讀 4653

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 問題的目標是給每個變數賦值使得所有條件得到滿足。

輸入格式:

第一行兩個整數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\)​∈),表示構造出的解。

輸入樣例#1:複製

3 11 1 3 0

輸出樣例#1:複製

possible

0 0 0

談談理解?

只會\(n+m\)時間複雜度的演算法。

對於乙個2-sat問題。有如下三種情況

1.如果a=1 那麼 b=1

轉化為圖論思想,如果我要選a則必須選b

不選a則一定不選b

對(a,b),(b1,a1)建邊。

2.要麼a=1,要麼b=1

那就是選a就不選b(a,b^1),

選b就不選a(b,a^1)

3.a一定要選

直接連邊(a^1,a)

首先可以知道, \(x_\)​ 和 \(x_\)​ 必須選擇且僅選擇乙個。那麼,因為 \(x_i=a\) 一定滿足,則 \(x_i!=a\) 的點不可以取。那麼,直接建邊 \((x_x_)\) 可以控制 \(x_\), 這個點一定不可選擇,否則無解。

然後用tarjan求一遍強聯通分量。可以發現每乙個強聯通分量裡面的情況是要麼選就一起選,不選就一起不選的。當乙個條件與它的反條件同時被選取,即在乙個強聯通分量時,是不成立的。要麼就是成立的。

那麼輸出呢?怎麼保證輸出的方案是正確?

根據2-sat的對稱原則。如果連的是雙向邊,那麼整個圖就是對稱的。那麼為什麼比較拓撲序就一定正確呢?

因為由對稱原則強聯通分量一定也是相同的。而根據強聯通分量被標記的時間順序,拓撲序一定能保證每個問題有正確解。

(好吧,還是有點繞)

#include#include#include#include#includeusing namespace std;

const int n=3000001;

int head[n],dfn[n],low[n];

int id,tot,num,cnt;

int n,m,top;

int vis[n],line[n],bl[n];

struct nodee[n<<1];

int read()

while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();

return x*w;

}void add(int from,int to)

void tarjan(int x)

else if(vis[v])

low[x]=min(low[x],dfn[v]);

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

}}bool t_sat()

int main()

if(t_sat())

else printf("impossible\n");

return 0;

}

模板 2 SAT 問題

2 sat問題主要解決的是一類二取一的問題.做法就是先建圖,然後跑tarjan,然後就判斷正負是否衝突,假如有衝突,就說明無解,否則就判斷哪個的序號大.話說我也不知道為什麼序號大就代表1.題幹 題目背景 2 sat 問題 模板 題目描述 有n個布林變數x1x 1x1 xnx nxn 另有m個需要滿足...

2 SAT 問題學習 模板

首先來看這樣一道題 gym 101201f illumination two sat 題目鏈結 題意 乙個n n的房子,有很多燈,每個格仔只能被上下方向照一次 左右方向照一次,每個燈可以選擇上下或是左右照,照明長度以自身位置為中心,占用2 r 1個格仔。問能否安排一種方案,使所有格仔滿足條件。析 典...

2 Sat模板詳解

這幾天看了一下2 sat,因為有tarjan以及拓撲排序等等的知識基礎,還是比較好理解的,我看到的有兩個模板,乙個是時間複雜度為o nm 另乙個時間複雜度為o m 但是第二種存在一種侷限,他只是能求解隨機的解,但是如果要是求解字典序最小的解,只能使用第一種解法.我們就用乙個例子來看一下第乙個模板 h...