BZOJ1854 [Scoi2010]游戏(并查集/二分图匹配)

本文介绍了一道关于装备选择的问题,并提供了两种不同的解决思路:一是利用并查集算法来确定不可选属性值;二是采用二分图匹配的方法找到第一个无法通过装备体现的属性值。两种方法各有特点,适合不同背景的读者。

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

一题多解,挺不错的题


解法一:并查集

【题解】

将一个装备抽象成一条边,它连接着编号为其属性值的两个结点 
这样,取装备等价于取边; 每个装备只能用一次,等价于在每条边上仅能取一个端点 
因此,连好所有的边,构成一个个连通块,它们产生了这样一条性质:
对于某一连通块,若其为一棵树,则它的所有结点(属性值)中,只有一个不能取。(因为树的边比点少一,每条边上只能取一个点)
                            若其含有环,则它的所有结点(属性值)都能取。(边数于节点数相等,每条边上只能取一个点)
那么,我们只需从小到大枚举每个属性值,若它所在的块为树,且它的值是树中结点的最大值,它就是第一个不能取的值 


【代码】

#include<stdio.h>
#include<stdlib.h>
int hash[10005],fa[1000005],max[1000005],hascir[1000005];
int father(int x)
{
	if(fa[x]!=x) fa[x]=father(fa[x]);
	return fa[x];
}
int main()
{
	int n,i,x,y;
	scanf("%d",&n);
	for(i=1;i<=10000;i++)//注意:不是从1到n循环(卡片属性可以超过n)
		fa[i]=i;
	for(i=1;i<=n;i++)
	{
		scanf("%d%d",&x,&y);
		hash[x]=hash[y]=1;
		if(father(x)==father(y)) hascir[fa[x]]=1;
		if(max[fa[x]]<x) max[fa[x]]=x;
		if(max[fa[x]]<y) max[fa[x]]=y;
		fa[fa[y]]=fa[x];
	}
	for(i=1;i<=n;i++)//答案不会超过n
	{
		x=father(i);
		if(hash[i]==0||(max[x]==i&&hascir[x]==0)) break;
	}
	printf("%d",i-1);
	return 0;
}


解法二:二分图匹配

【题解】

所有属性值为x集合,所有装备为y集合 
将y中的每个装备t与其在x集合中的属性值s1,s2连边 

因为每个装备只允许用一次,所以y中的一个元素它只能与x中的一个元素匹配 
这是一个二分图匹配问题 

给x中的结点(代表元素值)从小到大连匹配边,哪个结点找不到增广路,就代表这个属性值无法在比它小的值都出现的情况下通过装备体现出来,答案就得到了 


【代码】

#include<stdio.h>
#include<stdlib.h>
int v[2000005],first[10005],next[2000005],left[2000005],y[2000005];
int e=0,ans;
void tj(int x,int y)
{
	v[++e]=y;
	next[e]=first[x];
	first[x]=e;
}
int find(int x)
{
	int i;
	for(i=first[x];i!=0;i=next[i])
		if(y[v[i]]<ans)
		{
			y[v[i]]=ans;
			if(left[v[i]]==0|find(left[v[i]])==1)
			{
				left[v[i]]=x;
				return 1;
			}
		}
	return 0;
}
int main()
{
	int n,i,x,y;
	scanf("%d",&n);
	for(i=1;i<=n;i++)
	{
		scanf("%d%d",&x,&y);
		tj(x,i);
		tj(y,i);
	}
	for(ans=1;ans<=n;ans++)
		if(find(ans)==0) break;
	printf("%d",ans-1);
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值