2-SAT问题:有n个bool型的变量,有m个方程(每个方程有且只包含n个bool变量中的2个),
问能否找出满足这m个方程的n个bool变量。
解决2-SAT问题可以利用强连通分量。
一、建有向图
每个变量只有TRUE / FALSE
两种选择,我们可以把第i个变量拆成i / i+n
两个点,分别表示TRUE / FALSE
。再通过方程进行建边,转化成图论问题。
比如方程:x1 | x2 =TRUE (x1 x2至少有一个是true)
可以得到两条有向边:
x1+n -> x2
x2+n -> x1
(x1为假 那么一定可以得出x2为真 ,反之)
那么能否拿x1为真
连边呢?不行,因为x1为真,那么x2不管真假都可以,是不确定性的关系,所以不能连边。
这个题目中的方程:x1=p 或 x2=q 至少有一个满足
所以可以建两条有向边:
x1(¬p) -> x2(q)
x2(¬q) -> x1(p)
二、求出强连通分量
利用tarjan算法求出有向图的SCC,同时顺带求出了缩点后的逆拓扑序。
对于任意一个SCC,其中的每个顶点都是要同时取的值。
三、取bool值
在缩点后的DAG
中,如果i比i+n的拓扑序更大,那么肯定只能取i,因为如果取i+n的话,会指向i,造成i和i+n同时取的错误。
另外,如果i i+n位于同一个SCC中,那么问题无解。
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define pii pair<int,int>
const int maxn = 2e6+10;
const int mx = 40;
const int mod = 1e9+7;
const ll inf = 34359738370;
const int INF = 1e5;
vector<int> g[maxn];
int dfs_clock,scc_cnt;
int low[maxn],dfn