这是C++算法基础-数据结构专栏的第三十篇文章,专栏详情请见此处。
引入
上次我们学习了朴素版的并查集,并且实现了合并和查找的操作以及优化方法,但有时候,某些题目会让你求某个集合的大小,朴素版的并查集就无能为力了,所以我们今天就学习能维护大小的并查集。
维护大小版的并查集和朴素版的并查集的定义、操作和优化都是大致相同的,如果想了解具体内容,可以移步至我的这篇博客:并查集的实现(朴素版)。
在这里就不再详细讲解,只讲解主体过程qwq
下面我们就来讲并查集的实现(维护大小版)。
过程
例题:连通块中点的数量
题目大意:给定
个点,要求组成无向图。现在要进行
个操作,操作共三种:在点
和点
之间连一条边;询问点
和点
是否在同一个连通块中;询问点
所在连通块中点的数量。
维护大小
在上次的学习中,我们知道了在并查集合并时,除了路径压缩时一路上经过的点,部分节点没有被更新,所以只有根节点才是有用的。
那么如果要维护大小的话,我们就可以建一个新的数组,用来表示当前集合中的节点个数。加上前面的分析,我们又能得出,在合并时,我们将根节点的
更新,查询集合的大小时,只需像查找时一样,不停寻找到根节点,并输出其
即可。也就是说,
只有根节点的有意义。
另外,初始化时,每个都要赋值为
,因为每个点初始都是一个集合,大小都为
。
代码
下面给出朴素版并查集的实现代码:
int p[N],size[N];
int find(int x){
if(p[x]!=x) p[x]=find(p[x]);
return p[x];
}
for(int i=1;i<=n;i++){
p[i]=i;
size[i]=1;
}
size[find(b)]+=size[find(a)];
p[find(a)]=find(b);
代码解释
第一行是存储每个节点的祖宗节点的数组和存储当前集合中的节点个数的数组;find()函数的作用是寻找根节点;for循环中的内容的作用是初始化;最后一行的作用是合并。
上一篇-并查集的实现(朴素版) C++算法基础专栏文章 下一篇-并查集的实现(维护到祖宗节点距离版)与食物链(NOI2001)问题
每周一更新一篇文章,内容一般是自己总结的经验或是在其他网站上整理的优质内容
点个赞,关注一下呗~