luogu 4782【模板】 2-SAT 问题
2-SAT就是给出$m$个限制表示$x==val_x || y==val_y$
求出满足的解
每个点拆成两个点,如果$x$不满足则$y$一定满足,$y$不满足同理。这样我们连边,然后$tarjan$即可
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cstdlib> 5 #include<cmath> 6 #include<algorithm> 7 #include<queue> 8 #include<vector> 9 #include<map> 10 #include<set> 11 #define ll long long 12 #define db double 13 #define inf 2139062143 14 #define MAXN 2001000 15 #define rep(i,s,t) for(register int i=(s),i##__end=(t);i<=i##__end;++i) 16 #define dwn(i,s,t) for(register int i=(s),i##__end=(t);i>=i##__end;--i) 17 #define ren for(register int i=fst[x];i;i=nxt[i]) 18 #define pb(i,x) vec[i].push_back(x) 19 #define pls(a,b) (a+b)%MOD 20 #define mns(a,b) (a-b+MOD)%MOD 21 #define mul(a,b) (1LL*(a)*(b))%MOD 22 using namespace std; 23 inline int read() 24 { 25 int x=0,f=1;char ch=getchar(); 26 while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();} 27 while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();} 28 return x*f; 29 } 30 int n,m,nxt[MAXN<<1],fst[MAXN],to[MAXN<<1],cnt; 31 int dfn[MAXN],low[MAXN],bl[MAXN],stp,st[MAXN],top,scc; 32 void add(int u,int v) {nxt[++cnt]=fst[u],fst[u]=cnt,to[cnt]=v;} 33 void tarjan(int x) 34 { 35 st[++top]=x,dfn[x]=low[x]=++stp; 36 ren if(!dfn[to[i]]) {tarjan(to[i]);low[x]=min(low[x],low[to[i]]);} 37 else if(!bl[to[i]]) low[x]=min(low[x],dfn[to[i]]); 38 if(low[x]==dfn[x]) 39 {scc++;int now=0;while(now!=x) now=st[top--],bl[now]=scc;} 40 } 41 int main() 42 { 43 n=read(),m=read();int a,b,x,y;rep(i,1,m) 44 a=read(),x=read(),b=read(),y=read(), 45 add(a+(1^x)*n,b+y*n),add(b+(1^y)*n,a+x*n); 46 rep(i,1,n<<1) if(!dfn[i]) tarjan(i); 47 rep(i,1,n) if(bl[i]==bl[i+n]) return puts("IMPOSSIBLE"),0;puts("POSSIBLE"); 48 rep(i,1,n) printf("%d ",bl[i]>bl[i+n]); 49 }