32.并查集的常见用法详解优化-[STL模板]

32.并查集的常见用法详解优化-[STL模板]


My Blog[ 我的博客 ] :新零云博客-云翼校园计划

大家可以来学习学习噢!!!


文章目录

  • 32.并查集的常见用法详解优化-[STL模板]
  • My Blog[ 我的博客 ] :[新零云博客-云翼校园计划](http://112.124.15.70/)
      • 1.并查集的定义
      • 2.并查集的基本操作
      • 3.合并
      • 4.合并优化写法
      • 5.路径压缩
        • 1.例题(见算法笔记P332)
      • 6.总结

来自小白的凝视

1.并查集的定义

定义:维护集合的数据结构

支持操作:查找 合并
.
实现方法:数组


2.并查集的基本操作

①初始化

一开始每个元素都是独立的集合!(因此令father【i】= i )

int father[N];
for(int i=1;i<=N;i++) father[i]=i;

②查找
规定:一个集合只有一个根结点

思路:一直递归访问父亲节点,直至找到根结点(father[i]==i)

//递推写法
int sou(int x)
{
	while(x!=father[x])
	{
		x=father[x];
	}	
	return x;
} 
-----------------------------------
//递归写法
int sou(int x)
{
	if(x==father[x]) return x;
	else return sou(father[x]);
} 


3.合并

把两个集合合并成一个

思路:先判断两个集合是否属于同一集合,不同才可以合并,将一个集合根结点 指向另一个集合根结点

例如:
1.两个元素a,b 判断是否统一集合
2.合并 father[a]=b 或者 father[b]=a

void hebing(int a,int b)
{
	int ga=sou(a);  //查找a根结点
	int gb=sou(b);  //查号b根结点
	if(ga!=gb) father[ga]=gb;  //如果不同 a的根结点指向b根结点
}

千万不要写成 father[ a ] = b


4.合并优化写法

合并元素x和y时,先搜到它们的根结点,然后再合并这两个根结点,即把一个根结点的集改成另一个根结点。
这两个根结点的高度不同,如果把高度较小的集合并到较大的集上,能减少树的高度。
下面是优化后的代码,在初始化时用height[i]定义元素i的高度,在合并时更改。

void chushi()
{
   for(int i=1; i<=N;i++)
   {
        s[i]=i;
        height[i]=0;            //树的高度
   }
}
void hebing(int a, int b)        //优化合并操作
{  
    int ga =sou(a);
    int gb =sou(b);
    if (height[a]==height[b])
	{
        height[a]++;      //合并,树的高度加一
        s[b]=a;       
    }
    else
	{                            //把矮树并到高树上,高树的高度保持不变
        if(height[a]<height[b])  s[a]=b;
        else s[b]=a;
    }
}

5.路径压缩

32.并查集的常见用法详解优化-[STL模板]_第1张图片

int sou(int x)
{
	if(x==father[x]) return x;
	else
	{
		int y=sou(father[x]);
		father[x]=y;
		return y;
	}
} 

1.例题(见算法笔记P332)

输入n,m,表示n个人和m组,每组有两个人a,b表示ab是好朋友,将其分为一组。问最少有多少组?
输入:
4 5
1 4
2 3
输出:
2

#include 
using namespace std;
const int N=1000;
int father[N],high[N];
void chushi()
{
	for(int i=1;i<=N;i++) 
	{
		father[i]=i;
		high[i]=0;    //树的高度 
	}
}
int sou(int x)                  //路径压缩(优化搜索) 
{
	if(x==father[x]) return x;
	else
	{
		int y=sou(father[x]);
		father[x]=y;
		return y;
	}
} 
void hebing(int a,int b)   //合并优化
{
	a=sou(a);
	b=sou(b); 
	if(high[a]==high[b])
	{
		high[a]++;
		father[b]=a;
	}
	else
	{
		if(high[a]<high[b]) father[a]=b;
		else father[b]=a;
	}
}
int main()
{
	int n,m,a,b;
	cin>>n>>m;
	chushi();
	while(m--)
	{
		cin>>a>>b;
		hebing(a,b);
	}
	int ans=0;
	for(int i=1;i<=n;i++)
	{
		if(father[i]==i) ans++;
	}
	cout<<ans<<endl;
	return 0;
}


6.总结

1.并查集产生的集合都是一个数

2.并查集合并不会产生环


关注新零云博客,获取原创PDF!

在这里插入图片描述

更多原创教程请扫码关注博客
我将自己的原创技术系列文章,自学方法经验总结均已整理成带有目录的PDF,方便大家下载学习,且持续更新,可与我一起交流PDF上的内容,不仅能学习技术,更能一起交流学习方法!不断成长,尽在编码之外!可为大家免费提供教程视频!

你可能感兴趣的:(入门篇-算法初步)