给大家推荐一个关于2-SAT讲的不错的博客(自我认为)
2-SAT
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
const int N = 4e6+10;
int h[N],e[N],ne[N],idx;
int low[N], dfn[N], c[N], stack[N];
vector<int> scc[N];
int n, m, num, top, cnt;
bool ins[N];
void add(int a,int b) {
e[++idx] = b, ne[idx] = h[a], h[a] = idx;
}
void tarjan(int x) {
dfn[x] = low[x] = ++num;
ins[x] = 1;
stack[++top] = x;
for(int i = h[x]; i; i = ne[i]) {
int y = e[i];
if(!dfn[y]) {
tarjan(y);
low[x] = min(low[x],low[y]);
} else if(ins[y])
low[x] = min(low[x], dfn[y]);
}
if(low[x] == dfn[x]) {
int z;
cnt++;
do {
z = stack[top--];
c[z] = cnt;
ins[z] = false;
scc[cnt].push_back(z);
} while(x!=z);
}
}
int main() {
scanf("%d",&n);
scanf("%d",&m);
for(int i = 1; i <= m; i++) {
int a,x,b,y;
scanf("%d%d%d%d",&a,&x,&b,&y);
//"如果第a个数为0或第b个数为0"至少满足其一 a=1则b=0 b=1则a=0
if(x == 0 && y == 0) add(a + n,b), add(b + n,a);
//如果第a个数为0或第b个数为1"至少满足其一 a=1则b=1 b=0则a=0
if(x == 0 && y == 1) add(a + n,b + n), add(b, a);
//"如果第a个数为1或第b个数为0"至少满足其一 a=0则b=0 b=1则a=1
if(x == 1 && y == 0) add(a, b), add(b + n, a + n);
// "如果第a个数为1或第b个数为1"至少满足其一 a=0则b=1 b=0则a=1
if(x == 1 && y == 1) add(a, b + n), add(b, a + n);
}
for(int i = 1; i <= 2 * n; i++)
if(!dfn[i]) tarjan(i);
for(int x = 1; x <= n; x++) {
if(c[x] == c[x+n]) {
printf("IMPOSSIBLE\n");
return 0;
}
}
printf("POSSIBLE\n");
for(int i = 1; i <= n; i++) {
//强联通分量编号越小 -> 拓扑序越大 -> 越优
if(c[i] > c[i+n]) printf("1 ");
else printf("0 ");
}
return 0;
}