【图论】2018国庆三校联考D5T2

本文探讨了2SAT问题的解决策略,通过构建连边模型并枚举每种状态,确保加入最少的矛盾关系使无合法解。采用深度优先搜索判断合法性,详细解释了代码实现过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在这里插入图片描述

分析:

题意非常丑陋。。。简化出来就一句话:每个点有选中、未选中两种状态,现在给出一些矛盾关系,要求加入尽可能少的矛盾关系,使得没有合法方案。

如此2sat的模型,显然需要2sat的连边方式。。。然后直接枚举每个位置选、不选是否合法即可。若不选合法,则考虑其练的边是否有一个选择的点,如果有则可以用1的代价使得这个点不选非法。具体的情况见代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#define SF scanf
#define PF printf
#define MAXN 4010
using namespace std;
struct node{
	int x;
	node *nxt;	
}edge[MAXN*4];
node *head[MAXN],*ncnt=edge;
int n,m;
void add_edge(int u,int v){
	ncnt++;
	ncnt->x=v;
	ncnt->nxt=head[u];
	head[u]=ncnt;
}
bool vis[MAXN];
void dfs(int x){
	vis[x]=1;
	for(node *v=head[x];v!=NULL;v=v->nxt){
		int u=v->x;
		if(vis[u]==0)
			dfs(u);
	}
}
int query(int x){
	memset(vis,0,sizeof vis);
	dfs(x);	
	for(int i=1;i<=n;i++)
		if(vis[i]==1&&vis[i+n]==1)
			return 0;
	return 1;
}
int check(){
	for(int i=1;i<=n;i++)
		if(vis[i]==1)
			return 1;
	return 0;	
}
int l[MAXN];
int main(){
	freopen("god.in","r",stdin);
	freopen("god.out","w",stdout);
	int t;
	SF("%d",&t);
	while(t--){
		SF("%d%d",&n,&m);
		for(int i=1;i<=n*2;i++)
			head[i]=NULL;
		ncnt=edge;
		int ans=3,u,v;
		for(int i=1;i<=m;i++){
			SF("%d%d",&u,&v);
			if(u<0)
				u=-u+n;
			if(v<0)
				v=-v+n;
			add_edge(u,(v+n)%(2*n));
			add_edge(v,(u+n)%(2*n));
		}
		for(int i=1;i<=n;i++){
			int res1=query(i);
			int res2=query(i+n);
			int con=check();
			if(res2==0)
				ans=min(ans,res1);
			else if(con==1)
				ans=min(ans,1+res1);
		}
		if(ans==3)
			PF("No Way\n");	
		else
			PF("%d\n",ans);
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值