POJ--2723[Get Luffy Out] 第二道2—SAT

45 篇文章 0 订阅
题目大意:

有2n把钥匙,分成2组,给你每组的钥匙信息,并且每组的钥匙只能用一个。

有m个门,每个门有2个锁,只要打开一个锁这个门就开了。(顺序遇见m个门)

问你最多能够打开多少个门。

 

思路分析:

2n个钥匙,定义4n个节点,1~2n中的i表示用第i个钥匙。 2n+1~4n中的j, 表示不用j - 2n号钥匙。

那么对与给你的n组钥匙的每一组a和b。

有边<a, b + 2n> 和 <b, a + 2n>(只能选一个钥匙)

对于给你的m个门的两个锁a和b

有边<a + 2n, b> <b + 2n, a> 至少选一个。

然后枚举1~m个门,看看最后能到第几个门能够满足条件(数据比较少,不用二分也能过)

 

CODE:

/*POJ2-SAT第二题*/
/*AC代码:1000ms(没用二分)*/
#include <iostream>
#define MAXN 6000
struct edge
{
	int v,next;
	edge(){}
	edge(int v1,int next1)
	{
		v=v1;next=next1;
	}
}E[2000000];
int head[MAXN],ecnt;
int Low[MAXN],DFN[MAXN],Stack[MAXN],Belong[MAXN];
bool Instack[MAXN];
int cnt,Index,top,N,M;
void Insert(int u,int v)
{
	E[ecnt]=edge(v,head[u]);
	head[u]=ecnt++;
}
void Tarjan(int u)
{
	int v,i;
	Low[u]=DFN[u]=++Index;
	Instack[u]=true;
	Stack[++top]=u;
	for(i=head[u];i!=-1;i=E[i].next)
	{
		v=E[i].v;
		if(!DFN[v])
		{
			Tarjan(v);
			if(Low[u]>Low[v])
				Low[u]=Low[v];
		}
		else if(Instack[v]&&Low[u]>DFN[v])
			Low[u]=DFN[v];
	}
	if(Low[u]==DFN[u])
	{
		cnt++;
		do{
			v=Stack[top--];
			Belong[v]=cnt;
			Instack[v]=false;
		}while(v!=u);
	}
	return;
}
int main()
{
	int i,j,u,v;
	while(scanf("%d%d",&N,&M)!=EOF)
	{
		if(N==0&&M==0) break;
		ecnt=0;
		memset(head,-1,sizeof(head));
		for(i=0;i<N;i++)
		{
			scanf("%d%d",&u,&v);
			Insert(u,v+2*N);//注意,表示只能取一个
			Insert(v,u+2*N);
		}
		int ans=0;
		bool flag=true;
		for(i=0;i<M;i++)
		{
			scanf("%d%d",&u,&v);
			if(flag)
			{
				Insert(u+2*N,v);Insert(v+2*N,u);//表示只能不取一个(至少去一个)
				Index=cnt=top=0;
				memset(Instack,false,sizeof(Instack));
				memset(DFN,0,sizeof(DFN));
				memset(Low,0,sizeof(Low));
				for(j=0;j<2*N;j++)
					if(!DFN[j])
						Tarjan(j);
					for(j=0;j<N;j++)
						if(Belong[j]==Belong[j+2*N])
						{flag=false;break;}
						if(flag) ans++;
			}
		}
		printf("%d\n",ans); 
	}
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

__简言

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值