Codeforces Round #133 (Div. 2)B.Forming Teams(并查集)

 

 题解:

        经典的并查集问题,将每一个敌对元素之间有关联的可以联系成一个环。

1:判断是不是奇数环,若是奇数环,说明要去掉一个人,板凳席+1,若不是则刚好偶数环可以将其分到两队,板凳席不加人。

2:如果就是单纯是两两敌对,则这两个人自然就可以分到两个不同的队中,板凳席不用加人

3:如果没有任何敌对关系,也就是前两种处理好之后剩余的人,他们可以随意放置在不同的队伍中,没有什么关系,所以判断剩余人数的奇偶性,若是奇数则板凳席+1。

#include<iostream>
#include<algorithm>
using namespace std;
int fa[101],num[101];
int i,j,n,m,k,q;
int ans,x,y,px,py;

int find(int x)//并查集模板 
{
	if(x!=fa[x])
		fa[x]=find(fa[x]);
	return fa[x];//递归最后返回祖先 
} 
int main()
{
	while(scanf("%d%d",&n,&m)!=EOF){
		ans=0;
		for(i=0;i<=n;i++){//初始定义 
			fa[i]=i;
			num[i]=1;//环中个数 
		}
		while(m--){
			scanf("%d%d",&x,&y);//x,y有仇就放在一个环里 
			px=find(x);
			py=find(y);
			if(px!=py)//说明还没有闭环,继续处理该环 
			{
				fa[px]=py;
				num[py]+=num[px];//将y的子节点也就是他的环个数加到px树上去 
			}
			else//同宗的话:说明闭环了,可以开始结算环中元素的总个数了(因为题目给出一个人只有两个敌人,一开始已经有个敌人了,最后又出现一个敌人,说明闭环) 
			{
				k=num[px]&1;//如果num[px]为奇数则&1为1,是偶数则为0 
				ans+=k;
			}
		}
		q=(n-ans)&1;//最后出场去掉的人数:剩下的人若为奇数则减一 
		ans+=q;//加上最后去掉的个数 
		printf("%d\n",ans);
	}
	return 0;
} 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值