Skip to content

Commit

Permalink
Update 2-sat.md
Browse files Browse the repository at this point in the history
新增2-sat介绍
  • Loading branch information
CurryWOE authored Oct 30, 2023
1 parent 659078b commit 5cdc1fa
Showing 1 changed file with 34 additions and 0 deletions.
34 changes: 34 additions & 0 deletions docs/Graph/2-sat.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,38 @@
# 2-SAT
有 $n$ 个布尔变量 $x_i$ ,另有 $m$ 个需要满足的条件,每个条件形如 ["$x_i$ 为真" 或 "$x_j$ 为假"]["$x_i$ 为假" 或 "$x_j$ 为假"]

2-SAT 问题的目标是给每个变量赋值使得所有条件得到满足。

要满足 ["$x_i$ 为真" 或 "$x_j$ 为假"] 这个条件,显然能推出两结论: $x_i$ 为假必定有 $x_j$ 为假;$x_j$ 为真必定有 $x_j$ 为真

把A推导出B的逻辑关系,变成图上的有向边,每个变量有两个点,分别表示 $x_i$ 为真,$x_i$ 为假

当 $x_i$ 为真,$x_i$ 为假能互相推导(即鱼越大鱼越小的矛盾),反应在图上就是二者处于一个强连通分量,此时无解

当A能推导出非A,而非A不能推导出A,那么A只能是假;反之同理。反应在图上就是拓扑序越大的是所需答案,在我的SCC板子里就是所属强连通分量编号小

如果A和非A没有逻辑关系,那么取值随意
```cpp
for(int i=0;i<m;++i)
{
cin>>x>>a>>y>>b;//A_x为a或A_y为b
e[2*x-(!a)].push_back(2*y-b);
e[2*y-(!b)].push_back(2*x-a);
}
for(int i=1;i<=n*2;++i)
if(!dfn[i])
tarjan(i);
for(int i=1;i<=n;++i)
{
if(f[2*i]==f[2*i-1])
{
cout<<"IMPOSSIBLE";
return 0;
}
else
ans[i]=(f[2*i-1]<f[2*i]);
}
cout<<"POSSIBLE\n";
for(int i=1;i<=n;++i)
cout<<ans[i]<<" ";
```

0 comments on commit 5cdc1fa

Please sign in to comment.