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:
#includeusingview codenamespace
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;
}
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,根據...