《P4782 模板 2 SAT 問題》

2022-06-19 19:51:09 字數 1704 閱讀 3255

2 - sat問題:

就是一些元素,他們的值只能為布林值0,1.

給出一些限制關係,並且每對關係都是兩個數之間的。

讓你找出一組構造,讓所有關係都滿足。

解法:首先要建圖:

我們規定,a為1的點為a + n,a為0的點為a。

那麼對於給定的一對關係a , b。

如果是a == 1,b == 1,那麼說明a | b。

利用可以轉化為!a ->b,!b -> a。

然後我們連邊,即!a 到 b一條,!b 到 a一條。

若a == 0,b == 0 : !a | !b:

a -> !b,b -> !a。

其餘情況都同理轉化連邊即可。

然後我們tarjan對強連通分量去染色:

對於無解的情況:如果存在一組i 與 i+n在同乙個強連通分量中,那麼就是無解。

否則就有解:那麼此時它的值為col[i] > col[i + n]的布林值。

code:

#includeusing

namespace

std;

typedef

long

long

ll;typedef pair

pii;

const

int n = 1e6 + 5

;const

int m = 5e6 + 5

;const ll mod = 1e9 + 7

;#define pi acos(-1)

#define inf 1e9

#define dbg(ax) cout << "now this num is " << ax << endl;

namespace

fastio

while(c >= '

0' && c <= '9')

return x*f;

}}using

namespace

fastio;

int n,m,col[n << 1],dfn[n << 1],low[n << 1],tim = 0,clr = 0

;vector

g[n << 1

];stack

s;bool vis[n << 1

];void tarjan(int

u)

else

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

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

col[s.top()] =clr;

vis[s.top()] = 0

; s.pop();

}}int

main()

else

if(a == 1 && b == 1)

else

if(a == 1 && b == 0)

else

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

找環,注意是兩倍點

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

}printf(

"possible\n");

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

system(

"pause");

return0;

}

view code

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 問題

將每乙個點 x i 拆成 2i 和 2i 1 2i 表示 x i 的假狀態,2i 1 表示 x i 的真狀態 問題就化為了從2n個狀態中選出原來的每乙個 x i 的乙個狀態。這有什麼用呢?別急,先舉個栗子,1 1 3 0 就可以用有向邊 2 6 7 3 來表示,什麼意思呢?2表示1為false,根據...

題解 P4782 模板 2 SAT 問題

將每乙個點 x i 拆成 2i 和 2i 1 2i 表示 x i 的假狀態,2i 1 表示 x i 的真狀態 問題就化為了從2n個狀態中選出原來的每乙個 x i 的乙個狀態。這有什麼用呢?別急,先舉個栗子,1 1 3 0 就可以用有向邊 2 6 7 3 來表示,什麼意思呢?2表示1為false,根據...