Luogu P4782 [Template] 2-SAT problem

The 2-SAT problem can judge whether the conditions are contradictory through strong connected components.
The problem often requires an output scheme. When outputting the scheme, the scc value of the strongly connected component will be closely related to the topological order of the original image.
#include <bits/stdc++.h>
using namespace std;
const int N=1e6+5;
int n,m,a,b,nowa,nowb;
int cnt,head[N<<1];
int col,now,top,dfn[N<<1],low[N<<1],color[N<<1],sta[N<<1],si[N<<1];
bool jay;
struct edge{
    
    int next,from,to;}e[N<<1];

inline void add(int u,int v)
{
    
    
	cnt++;
	e[cnt].next=head[u];
	e[cnt].from=u; 
	e[cnt].to=v;
	head[u]=cnt;	
}

inline void tarjan(int u)
{
    
    
    dfn[u]=low[u]=++now;
    sta[++top]=u;	
    for (register int i=head[u]; i; i=e[i].next)
    {
    
    
        if (!dfn[e[i].to])
        {
    
    
            tarjan(e[i].to);
            low[u]=min(low[u],low[e[i].to]);
        }
        else if (!color[e[i].to])
        low[u]=min(low[u],dfn[e[i].to]);
    }
    if (low[u]==dfn[u])
    {
    
    
        color[u]=++col;
        si[col]++;
        while (sta[top]!=u) color[sta[top]]=col,si[col]++,top--;
        top--;
    }
}

int main(){
    
    
	scanf("%d%d",&n,&m);
	for (register int i=1; i<=m; ++i)
	{
    
    
		scanf("%d%d%d%d",&a,&nowa,&b,&nowb);   
		//节点a表示条件a选0,节点a+n表示条件a选1。 
		add(a+(nowa^1)*n,b+nowb*n);     //如果a的条件不满足,那么就必须要满足b的条件
		add(b+(nowb^1)*n,a+nowa*n);     //如果b的条件不满足,那么就必须要满足a的条件 
	}
	for (register int i=1; i<=2*n; ++i) if (!dfn[i]) tarjan(i);
	jay=true;
	for (register int i=1; i<=n; ++i) if (color[i]==color[i+n]) {
    
    jay=false; break;}
	//如果i的条件不满足,就必须满足i的条件...明显矛盾,所以"IMPOSSIBLE" 
	//或者这样理解:如果i=0,那么i必须等于1;如果i=1,那么i必须等于0
	//所以,请问i到底是等于0还是等于1呢?既然没有这样的i,那么就是"IMPOSSIBLE" 
	if (!jay) puts("IMPOSSIBLE");
	else 
	{
    
    
		puts("POSSIBLE");
		for (register int i=1; i<=n; ++i) 
		if (color[i+n]<color[i]) printf("%d ",1); else printf("%d ",0); 	 
		//color[i+n]<color[i],根据tarjan缩点和拓扑序的性质,可以得到i可以走到i+n
		//意思就是:如果i=0,那么i就要等于1,i不能分身啊,所以i就只能等于1了... 
		//而如果color[i+n]>color[i],可以得到i+n可以走到i
		//意思就是:如果i=1,那么i就要等于0,所以我们只能让i等于0了。 
	}
return 0;
}

Guess you like

Origin blog.csdn.net/Dove_xyh/article/details/108559581