2-SAT

本篇引用自大佬的洛谷日报

P4782 【模板】2-SAT 问题

模板题

点击查看代码
#include<bits/stdc++.h>
#define int long long
#define inf 1e18
#define inc 0xcfcfcfcf
#define N 1000007
#define M 500007
#define mod 1000000007
//#pragma GCC optimize(2)
//#pragma GCC optimize(3)
using namespace std;
struct Edge
{
	int to,nxt;
}edge[N<<1];
int head[N<<1],dfn[N<<1],low[N<<1],belong[N<<1];
bool vis[N<<1];
int T=1,n,m,ecnt,tcnt,bcnt;
stack<int> stk;
void Add(int u,int v)
{
	edge[++ecnt]=(Edge){v,head[u]};
	head[u]=ecnt;
}
void Tarjan(int u)
{
	dfn[u]=low[u]=++tcnt;
	vis[u]=1;
	stk.push(u);
	for(int i=head[u];i;i=edge[i].nxt)
	{
		int v=edge[i].to;
		if(!dfn[v])
		{
			Tarjan(v);
			low[u]=min(low[u],low[v]);
		}
		else
			if(vis[v])
				low[u]=min(low[u],dfn[v]);
	}
	if(low[u]==dfn[u])
	{
		int v;
		++bcnt;
		do
		{
			v=stk.top();
			stk.pop();
			vis[v]=0;
			belong[v]=bcnt;
		}while(u!=v);
	}
}
bool Two_sat()
{
	tcnt=bcnt=0;
	for(int i=1;i<=2*n;++i)
		if(!dfn[i])
			Tarjan(i);
	for(int i=1;i<=n;i++)
		if(belong[i]==belong[i+n])
			return 0;
	return 1;
}
bool Solve()
{
 	//freopen("test.vis","r",stdin);
	scanf("%lld%lld",&n,&m);
	ecnt=0;
	for(int i=1;i<=m;++i)
	{
		int x,y,a,b;
		scanf("%lld%lld%lld%lld",&x,&a,&y,&b);
		int aa=a^1,bb=b^1;
		Add(x+aa*n,y+b*n);
		Add(y+bb*n,x+a*n);
	}
	if(Two_sat())
	{
		printf("POSSIBLE\n");
		for(int i=1;i<=n;++i)
			printf("%lld ",belong[i]>belong[i+n]);
	}
	else
		printf("IMPOSSIBLE");
	return true;
}
signed main()
{
	//scanf("%lld",&T);
	while(T--)
		if(!Solve())
			printf("-1\n");
	return 0;
}
/*
-std=c++11
-std=c99
*/


P4171 [JSOI2010] 满汉全席

只说明一下连边方案,对于一个评委,a,b要求至少满足其一,则a不满足时推出b一定满足,同理b不满足时a一定成立

点击查看代码
#include<bits/stdc++.h>
#define int long long
#define inf 1e18
#define inc 0xcfcfcfcf
#define N 10007
#define M 500007
#define mod 1000000007
//#pragma GCC optimize(2)
//#pragma GCC optimize(3)
using namespace std;
struct Edge
{
	int to,nxt;
}edge[N<<1];
int head[N<<1],dfn[N<<1],low[N<<1],belong[N<<1];
bool vis[N<<1];
int T=1,n,m,ecnt,bcnt,tcnt;
stack<int> stk;
void Add(int u,int v)
{
	edge[++ecnt]=(Edge){v,head[u]};
	head[u]=ecnt;
}
void Tarjan(int u)
{
	dfn[u]=low[u]=++tcnt;
	vis[u]=1;
	stk.push(u);
	for(int i=head[u];i;i=edge[i].nxt)
	{
		int v=edge[i].to;
		if(!dfn[v])
		{
			Tarjan(v);
			low[u]=min(low[u],low[v]);
		}
		else
			if(vis[v])
				low[u]=min(low[u],dfn[v]);
	}
	if(low[u]==dfn[u])
	{
		int v;
		++bcnt;
		do
		{
			v=stk.top();
			stk.pop();
			vis[v]=0;
			belong[v]=bcnt;
		}while(u!=v);
	}
}
bool Two_sat()
{
	tcnt=bcnt=0;
	for(int i=1;i<=2*n;++i)
		if(!dfn[i])
			Tarjan(i);
	for(int i=1;i<=n;i++)
		if(belong[i]==belong[i+n])
			return 0;
	return 1;
}
bool Solve()
{
 	memset(vis,0,sizeof(vis));
 	memset(belong,0,sizeof(belong));
 	memset(dfn,0,sizeof(dfn));
 	memset(low,0,sizeof(low));
 	memset(head,0,sizeof(head));
 	while(!stk.empty())
 		stk.pop();
	ecnt=0;
	scanf("%lld%lld",&n,&m);
	for(int i=1;i<=m;++i)
	{
		char in1,in2;
		int a,b;
		scanf(" %c%lld %c%lld",&in1,&a,&in2,&b);
		int x=(in1=='h'),y=(in2=='h');
		Add(a+(x^1)*n,b+y*n);
		Add(b+(y^1)*n,a+x*n);
	}
	if(Two_sat())
		printf("GOOD\n");
	else
		printf("BAD\n");
	return true;
}
signed main()
{
	scanf("%lld",&T);
	while(T--)
		if(!Solve())
			printf("-1\n");
	return 0;
}


posted @   模拟退火  阅读(20)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效
点击右上角即可分享
微信分享提示