tarjan算法求解2-SAT问题

在这里插入图片描述
题目链接:点击这里
代码如下:

#include <cstdio>
#include <cstring>
#include <vector>
#include<iostream>
#include <algorithm>
#define maxd 2020
using namespace std;
int n,m,tot=0;//n个点,m条边 
struct node{
    
    
	int to,next;
}edge[500050];
int numedge=0;//链式前向星存边用 
int head[maxd],low[maxd],dfn[maxd],belong[maxd];
//belong 相同的属于同一个强连通分量 num代表强连通分量所含的点数
int scc=0,cnt=0,top=0;
int stack[maxd];
bool instack[maxd];
void addedge(int u,int v){
    
    
	edge[++numedge].to=v;
	edge[numedge].next=head[u];
	head[u]=numedge;
}
void tarjan(int u){
    
    //中规中矩的tarjan
	stack[++top]=u;
	low[u]=dfn[u]=++cnt;
	instack[u]=true;
	for(int i=head[u];i;i=edge[i].next){
    
    
		int v=edge[i].to;
		if(!dfn[v]){
    
    
			tarjan(v);
			low[u]=min(low[u],low[v]);
		}
		else if(instack[v]) low[u]=min(low[u],dfn[v]);
	}
	if(low[u]==dfn[u]){
    
    
		++scc;
		do{
    
    
			instack[stack[top]]=false;
			belong[stack[top]]=scc;
		}while(u!=stack[top--]);
	}
}
void init(){
    
    //初始化
	tot=0;
	numedge=0;
	scc=0,cnt=0,top=0;
	memset(head,0,sizeof(head));
	memset(low,0,sizeof(low));
	memset(dfn,0,sizeof(dfn));
	memset(belong,0,sizeof(belong));
	memset(stack,0,sizeof(stack));
	memset(instack,0,sizeof(instack));
}
bool solve(){
    
    
	for(int i=0;i<2*n;++i){
    
    
		if(!dfn[i]) tarjan(i);
	}
	for(int i=0;i<2*n;i+=2){
    
    
		if(belong[i]==belong[i+1]) return 0;
	}//丈夫和妻子不能同时出席,故如果在同一个强连通分量中,那么返回false
	return 1;
}
int main() {
    
    
	while(~scanf("%d%d",&n,&m)){
    
    
		init();
		for(int i=1;i<=m;++i){
    
    
			int a1,a2,c1,c2;
			scanf("%d%d%d%d",&a1,&a2,&c1,&c2);
			addedge(2*a1+c1,2*a2+1-c2);
			addedge(2*a2+c2,2*a1+1-c1);
		}
		if(solve()){
    
    
			printf("YES\n");
		}
		else{
    
    
			printf("NO\n");
		}
	}
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_45695839/article/details/109407962
今日推荐