2-SAT模版

本文详细介绍了2-SAT问题的解决算法,采用Tarjan算法进行强连通分量分析,实现复杂度为O(n+m),其中n为变量数,m为约束数。通过具体代码实现,展示了如何利用深度优先搜索和强连通分量的概念来求解2-SAT问题。

复杂度 O ( n + m ) O(n+m) O(n+m)

原理证明 侵删

爆搜模版在这里 侵删

const int maxn = 2e6+1000;

vector<int> g[maxn];
int low[maxn],dfn[maxn];
int scc[maxn];
int sta[maxn];
bool vis[maxn];
int num=0,ind=0;
int cnt=0;

int n,p,M,m;
int tol;

int fid(int x){
	return p+x;
}

int yid(int x){
	return 2*x-1;
}

int nid(int x){
	return 2*x;
}

void tarjan(int u){
	vis[u]=1;
	dfn[u]=low[u]=++num;
	sta[++ind]=u;
	for(auto i:g[u]){
		if(!dfn[i]){
			tarjan(i);
			low[u]=min(low[u],low[i]);
		}else if(vis[i]){
			low[u]=min(low[u],low[i]);
		}
	}
	if(dfn[u]==low[u]){
		++cnt;
		do{
			vis[sta[ind]]=0;
			scc[sta[ind]]=cnt;
			--ind;
		}while(u!=sta[ind+1]);
	}
}

int ans[maxn];
int f;

void _2sat(){
	tol=(p+M)*2;
	for(int i=1;i<=tol;++i){
		if(!dfn[i]){
			tarjan(i);
		}
	}
	int ft=0;
	for(int i=1;i<=p;++i){
		int yx=yid(i),nx=nid(i);
		if(scc[yx]==scc[nx]) {
			cout<<-1<<endl;
			return ;
		}
		if(scc[yx]<scc[nx]){
			ans[ft++]=i;
		}
	}
	for(int i=1;i<=M;++i){
		int yx=yid(fid(i)),nx=nid(fid(i));
		if(scc[yx]==scc[nx]) {
			cout<<-1<<endl;
			return ;
		}
		if(scc[yx]<scc[nx]){
			f=i;
		}
	}
	cout<<ft<<" "<<f<<endl;
	for(int i=0;i<ft;++i){
		cout<<ans[i]<<" ";
	}
	cout<<endl;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值