2-SAT-学习笔记
基本知识复习
https://oi-wiki.org/graph/2-sat/
模板
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int N = 2e6+5;
int n,m;
int cvrt(int u, int tp) { return tp?u:u+n; }
vector<int> g[N];
int dfn[N],low[N],col[N],st[N],tp,in_st[N],ct,ncol;
void tarjan(int u)
{
dfn[u]=low[u]=++ct;
st[++tp]=u; in_st[u]=1;
for(int v:g[u])
if(!dfn[v]) tarjan(v),low[u]=min(low[u],low[v]);
else if(in_st[v]) low[u]=min(low[u],dfn[v]); // 这第二个一定是 dfn[v]
if(dfn[u]==low[u])
{
ncol++; int v;
do { v=st[tp--],in_st[v]=0,col[v]=ncol; } while(u!=v); // 这边我写法很容易搞错 tcl
}
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1,ti,ta,tj,tb; i<=m; i++)
{
scanf("%d%d%d%d",&ti,&ta,&tj,&tb);
if(ti==tj and ta!=tb) continue;
g[cvrt(ti,!ta)].push_back(cvrt(tj,tb)); // !i->j
if(ti==tj and ta==tb) continue;
g[cvrt(tj,!tb)].push_back(cvrt(ti,ta)); // !j->i
}
for(int i=1; i<=(n<<1); i++) if(!dfn[i]) ct=0,tarjan(i);
for(int i=1; i<=n; i++) if(col[i]==col[i+n]) { puts("IMPOSSIBLE"); return 0; } //如果 !u->u and u->!u 肯定是假的
puts("POSSIBLE");
for(int i=1; i<=n; i++) printf("%d ",(col[i]<col[i+n])); //肯定选拓扑序靠后的,也就是 col 小的 注意 tarjan 是反的拓扑序
return 0;
}