Poj 2492 Cf 100923这辈子都学不会的带权并查集(种类并查集篇章)

POj2492:http://poj.org/problem?id=2492

题意:给你n个虫子,有个人给你m对匹配关系,问你是否出现一对都是同性的情况。

思想:带权并查集数组出现每个的性别,即非0即1,如果都在一个块里面,判断他们的号是否相同,相同就不行,如果不在一个块里,那么就连接2个块,那么就更改某一个的原来的头的性别,然后下次用的时候更新下即可。

至于为何这样去更改原来父亲节点的权值,可以自己去算一下4种可能,发现就是这样。

#include<stdio.h>
int fa[2005];
int sum[2005]; 
int find(int x)
{
	if(x==fa[x])
		return x;
	int fx=fa[x];
	fa[x]=find(fa[x]);
	sum[x]=(sum[x]+sum[fx])%2;//连接之后更新关系 从后往前 
	return fa[x];
}
int main()
{
	int t;
	scanf("%d",&t);
	for(int Case=1;Case<=t;Case++)
	{
		int n,m,flag;
		flag=1;
		scanf("%d%d",&n,&m);
		for(int i=0;i<=n;i++)
		{
			fa[i]=i;
			sum[i]=0;
		}
		for(int i=0;i<m;i++)
		{
			int u,v;
			scanf("%d%d",&u,&v);
			if(flag==0)//已经错了 
				continue;
			int fx=find(u);
			int fy=find(v);
			if(fx==fy)//在一个链里面 
			{
				if((sum[u]+sum[v])%2==0)//说明在一起的而且是一个种类 
					flag=0;
			} 
			else//2个链 
			{
				fa[fx]=fy;
				sum[fx]=(sum[u]+sum[v]+1)%2; 
			}
		}
		printf("Scenario #%d:\n",Case);
		if(flag)
			printf("No suspicious bugs found!\n");
		else
			printf("Suspicious bugs found!\n");
		printf("\n");
	}
	return 0;
} 

codeforces:http://codeforces.com/gym/100923/problem/H

题意:已知有n个战士,分属于两个红、蓝阵营,现输入m条敌对关系,当本条关系信息与之前的真的关系信息冲突,则认为本条关系信息为假(即先输入的敌对关系优先为真)。

#include<stdio.h>
int fa[200005];
int sum[100005]; 
int find(int x)
{
	if(x==fa[x])
		return x;
	int fx=fa[x];
	fa[x]=find(fa[x]);
	sum[x]=(sum[x]+sum[fx])%2;//连接之后更新关系 从后往前 
	return fa[x];
}
int main()
{
	int t;
	freopen("meciul.in", "r", stdin);
    freopen("meciul.out", "w", stdout);
	scanf("%d",&t);
	for(int Case=1;Case<=t;Case++)
	{
		int n,m,flag;
		flag=1;
		scanf("%d%d",&n,&m);
		for(int i=0;i<=n;i++)
		{
			fa[i]=i;
			sum[i]=0;
		}
		for(int i=0;i<m;i++)
		{
			int u,v;
			scanf("%d%d",&u,&v);
			int fx=find(u);
			int fy=find(v);
			if(fx==fy)//在一个链里面 
			{
				if((sum[u]+sum[v])%2==0)//说明在一起的而且是一个种类 
					printf("NO\n");
				else
					printf("YES\n");
			} 
			else//2个链 
			{
				printf("YES\n");
				fa[fx]=fy;
				sum[fx]=(sum[u]+sum[v]+1)%2; 
			}
		}
	}
	return 0;
} 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值