2-sat问题简介

对于2-sat问题的每一个约束:两个条件中至少满足一个;
这里加入满足 x ∣ y x|y xy,只需要 x x x或者 y y y满足条件就可以了。
那么如果 x x x不满足条件,那么 y y y必须满足条件;反之亦然;
那么就可以对于这种约束条件建边在 x x x不满足条件的情况下, y y y必须满足条件,即 ! x − > y !x->y !x>y;同理可以知道 ! y − > x !y->x !y>x
这个建边方式可以推广到一般的约束中去,只要是2-sat,即两者之间的约束都可以(约束关系只在x,y之间)。

这样的话,对于图中的联通块,必须同时满足条件,然后可以随便构造出一组解就可以了。对于所在的联通块,有个拓扑关系。只需要所有的拓扑关系都统一构造方式(我一般用ring[x]<ring[x+n]的x为1),就可以得到唯一解;
如果x=0和x=1在一个联通块中,就不满足条件;

这里附上代码:

void dfs(int u){
	dfn[u]=low[u]=++cnt;
	st[++top]=u;
	For(i,0,G[u].size()-1){
		int v=G[u][i];
		if(!dfn[v]){
			dfs(v);
			low[u]=min(low[u],low[v]);
		}
		else if(!ring[v]) low[u]=min(low[u],dfn[v]);
	}
	if(dfn[u]==low[u]){
		int v;
		++tot;
		do{
			v=st[top--];
			ring[v]=tot;
		}while(u!=v);
	}
}

	For(i,1,m){
		int x,a,y,b;
		scanf("%d%d%d%d",&x,&a,&y,&b);//x 0|1 y 0|1
		G[x+(a&1)*n].push_back(y+(b^1)*n);
		G[y+(b&1)*n].push_back(x+(a^1)*n);
	}
	For(i,1,n<<1) if(!dfn[i]) dfs(i);

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值