并查集

说明

近几天在自学并查集,并且看了一些博客觉得他们讲的听清楚的,很容易懂,都是生动教学,把队首

的那个下标比喻为掌门,我在这里就不比作掌门了,毕竟我和他们不一样。下面,开始说一下简单并

查集是个什么东西,以及类似题目求解。

并查集定义

并查集,在一些有N个元素的集合应用问题中,我们通常是在开始时让每个元素构成一个单元素的集

合,然后按一定顺序将属于同一组的元素所在的集合合并,其间要反复查找一个元素在哪个集合中。

这一类问题近几年来反复出现在信息学的国际国内赛题中,其特点是看似并不复杂,但数据量极大,

若用正常的数据结构来描述的话,往往在空间上过大,计算机无法承受;即使在空间上勉强通过,运

行的时间复杂度也极高,根本就不可能在比赛规定的运行时间(1~3秒)内计算出试题需要的结果,

只能用并查集来描述。

并查集思路

并查集就在于找到每一串的第一个元素的作比较,在这里我们就把每一叫做一个队伍,而站在队伍第

一个人就是队长,刚刚开始的时候就是在还不知道谁和谁是一队的,就可以每个人都是队长,然后再

确定关系,比如两个人确定关系,就找着两个人的队长如果队长是一样的,那就说明这俩个人是一个

队伍里面的人,就没必要再合并了,如果队长不一样就说明这俩个队伍应该是一个队伍,就将俩个队

伍合并为一个队伍就行,如此操作,最终有联系的成员都会在一个队伍里面。

简单例题及解法

题目:朋友圈

有n个人,编号1-n。
现在有一个舞会,在舞会上,大家会相互介绍自己的朋友。
即: 如果a认识b,b认识c。那么在舞会上,a就会通过b认识到c。
现在,给出m个关系
每个关系描述:
a b
表示 编号为a和编号为b的人是朋友关系。
样例输入:
5 3
1 2
2 3
4 5
样例输出:
2

解题:

希望读者结合本人上面写的并查集思路一起看。

首先假设这个队伍的每个人都是队长,我们设指向自己的人是队长,然后等着确定关系,当有俩个人

确定关系的时候我们就可以找他们的队长,队长不一样就可以合并,合并也很简单,即让第一个的队

长指向第二个人的队长,或者让第二个人的队长指向第一个人的队长,这样就变成了一个队长,也就

变成了一个队伍,当确定完之后,再找有多少队长,就是有多少朋友圈了。

#include<stdio.h>
int search(int a[],int people)
{
 int memory=people;//记住进来的那个人的位置 
 while(a[people]!=people)//找队长 
  people=a[people];
 a[memory]=people;
 //直接让进来的那个人指向第一个人,压缩路径,就是不用跳那么多下到队长那里 
 return people;//返回队长的位置 
}
int main()
{
 int n,m;
 while(~scanf("%d%d",&n,&m))
 {
  int a[100010]={0};
  int b,c,cnt=0;
  int i,leader1,leader2;
  for(i=1;i<=n;i++)a[i]=i;//假设全部都是一队一个人,指向自己的人就是队长,全部是队长 
  for(i=0;i<m;i++)
  {
   scanf("%d%d",&b,&c);//需要加到一个组的俩人 
   leader1=search(a,b);//寻找b的队长 
   leader2=search(a,c);//寻找c的队长 
   if(leader1!=leader2)//俩个队长不一样就要合并俩个队,让队长变成其中一个就行了 
    a[leader1]=leader2;//让其中一个队长指向另一个队长就合并了 
  }
  for(i=1;i<=n;i++)//计算有多少队长就有多少队伍 
   if(a[i]==i)cnt++;//如果他指向自己他就是队长 
  printf("%d\n",cnt);
 } 
 return 0;
}

并查集就到这,不懂的可以留言问我。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值