并查集(Union-Find)

目的:主要用来解决动态连通性问题 (数据结构用来表征站点之间的连通性,算法主要利用数据结构,解决问题,比如,判断站点之间是否连通。由此,数据结构的特性对算法性能有着最直接的影响,数据结构和算法设计就是两个好基友,谁也不能脱离谁。)

应用:声明的两个变量是否指向同一个对象(内存空间);网络中两个主机之间是否相连;两个数据是否在同一个集合里。
输入:整数对序列, 例如<p, q>对,代表p和q是相连通的。
方法:对输入的<p,q>对进行判断,若已有的值对表明p,q已经连通,则忽视这一输入,否则将他们所在的component进行归并。

基于上述要求,提出下述几个最基本的API:

UF(int N)  用(0, N-1)初始化N个站点。

void union(int p, int q)  如果p与q这两个站点处于不同的compnent中,将这两个站点所在的component归并。

int find(int p) 返回站点p所在的component标号。

boolean connected(int p, int q) 判断站点p与q是否处于同一个component中。

int count() 返回component数目。

基本java的代码实现:

public class UF

{

private int[] id;

private int count; //UF数据结构需要维护两个量,一个是id数组,存储所有的站点对应的component号;还有一个是count,总计有多少个components。

public UF(int N) {count N; id =new int[N]; for(int i=0; i<N; i++) id[i]=i;} //构造函数,初始化成员变量。

public void union(int p, int q);

public int find(int p){return id[p];}

boolean connected(int p, int q} { if(find(p)==find(q) return true; else return false;}

public int count() { return count;}

}

public void union(int p, int q)

{

int pID=find(p);

int qID=find(q);

if(pID==qID) return; //如果它俩有处在同一个component中,则啥也不做。

for(int i=0; i<id.length;i++)

if(id[i]==pID) id[i]=qID;  //如果p和q是不相连的,将这两个站点所在的component合并,p所在的component中所有站点的id号都被替换为q所在component站点号。其实这是随意的,也可以用q的站点号来替换掉p所在component的所有站点号。

count--; //component数目消失一个。

}

时间: 2024-10-19 11:52:15

并查集(Union-Find)的相关文章

POJ 1611 The Suspects 并查集 Union Find

本题也是个标准的并查集题解. 操作完并查集之后,就是要找和0节点在同一个集合的元素有多少. 注意这个操作,须要先找到0的父母节点.然后查找有多少个节点的额父母节点和0的父母节点同样. 这个时候须要对每一个节点使用find parent操作.由于最后状态的时候,节点的parent不一定是本集合的根节点. #include <stdio.h> const int MAX_N = 30001; struct SubSet { int p, rank; }sub[MAX_N]; int N, M; v

并查集(Union Find):实现及其优化(c++)

1.什么是并查集 并查集是用来管理元素分组的数据结构.可以高效进行如下操作: 查询元素a.b十是否在同一组 合并a.b所在的组 并查集可以进行合并操作但不能进行分割操作. 2.并查集的结构 并查集采用多叉树形结构实现,每个元素对应一个结点,每个组对应一棵树.重点关注结整体形成一个树形结构,而不是树的形状等信息. 3.并查集的实现 3.1 初始化 对于并查集,一般采用数组来实现,其中元素为数组的索引,其父辈为数组索引对应内容. 在初始化中,将每个元素父辈设为自己,即自己形成一组,并对用一个rank

【算法学习笔记】41.并查集 SJTU OJ 1283 Mixture

---恢复内容开始--- Description CC非常喜欢化学,并且特别喜欢把一大堆液体倒在一起. 现在CC有n种液体,其中m对会发生反应,现在她想把这n种液体按某种顺序倒入一个容器内,让她获得最刺激的体验,使危险系数尽量大. 我们可以这样计算危险系数,一开始容器内没有任何液体,危险系数为1.每次液体倒入容器时,若容器内已有一种或多种液体会与这种液体发生反应,则危险系数会乘2,否则危险系数不变. 请你求出把这n种液体倒在一起的最大危险系数. Input Format 第一行为两个数n和m.

并查集(union/find)

在计算机科学中,并查集是一种树型的数据结构,其保持着用于处理一些不相交集合(Disjoint Sets)的合并及查询问题.有一个联合-查找算法(union-find algorithm)定义了两个操作用于此数据结构: Find:确定元素属于哪一个子集.它可以被用来确定两个元素是否属于同一子集. Union:将两个子集合并成同一个集合. 因为它支持这两种操作,一个不相交集也常被称为联合-查找数据结构(union-find data structure)或合并-查找集合(merge-find set

HDU 1035 Robot Motion Union Find 并查集题解

本题的类型我一看就想到使用并查集解了,因为要查找是否有环,这是并查集的典型用法. 但是由于本题数据实在是太水了,故此有人使用直接模拟都过了.这让本题降了个档次. 这里使用并查集解.而且可以根据需要简化并查集函数,代码还是很好打的. #include <stdio.h> #include <vector> #include <string.h> #include <algorithm> #include <iostream> #include &l

POJ 2524 Ubiquitous Religions Union Find 并查集

本题是标准的并查集了,最后利用这些集求有多少独立集. 所以这里也写个标准程序过了. 最后查找独立集合: 看有多少个节点的父母节点是自己的,那么就是独立集合了.自己做自己的父母当然最独立的了,没有任何依赖,呵呵. #include <stdio.h> const int MAX_N = 50001; //const int MAX_M = MAX_N/2 * (MAX_N-1) + 1; int N, M; struct SubSet { int p, r; }; SubSet sub[MAX_

并查集(不相交集)的Union操作

在并查集(不相交集)中附加操作\(Deunion\),它实现的功能是取消最后一次\(Union\)的操作. 实现思想 初始化一个空栈,将每一次的\(Union\)操作的两个集合的根和其值\(Push\)入栈:若执行\(Deunion\)操作时,只需要对栈进行\(Pop\)操作即可.在没有路径压缩时,这个策略是有效的:若并查集(不相交集)实现了路径压缩,将使得\(Deunion\)操作很难进行,因为路径压缩有很大的概率将本来属于一个根下的元素连接到另一个根,若此时执行\(Union\)操作时,很难

UVALive 6910 Cutting Tree(并查集应用)

总体来说,这个题给的时间比较长,样例也是比较弱的,别的方法也能做出来. 我第一次使用的是不合并路径的并查集,几乎是一种暴力,花了600多MS,感觉还是不太好的,发现AC的人很多都在300MS之内的过得. 看到他们的做法后,我知道了这个题比较好的做法. 逆向思维的并查集,因为这里只有去边操作,完全可以离线计算,把删边当成加边,然后逆序输出答案即可. 但是,这个却有一个坑,很坑,只有第一次删除的时候,我们才对他进行操作,加边的时候也只能在第一次删除的时候加.当时因为这里,十分困惑-- 这是我无路径压

poj1611 并查集 (路径不压缩)

http://poj.org/problem?id=1611 题目大意: 有一个学校,有N个学生,编号为0-N-1,现在0号学生感染了非典,凡是和0在一个社团的人就会感染,并且这些人如果还参加了别的社团,他所在的社团照样全部感染,求感染的人数. 解题思路: 并查集的变种,实质就是求0所在的强连通图的结点数目. 这道题纠结在数据的输入上,他只是告诉你哪些学生是同一个社团的.这就需要处理一下,我的想法是:如果这个社团有num个孩子,new出一个大小为num的数组,第一个孩子不处理,从第二个孩子起,和

并查集的应用

定义 并查集是一种树型的数据结构,用于处理一些不相交集合(Disjoint Sets)的合并及查询问题.常常在使用中以森林来表示. 应用 若某个朋友圈过于庞大,要判断两个人是否是在一个朋友圈,确实还很不容易,给出某个朋友关系图,求任意给出的两个人是否在一个朋友圈. 规定:x和y是朋友,y和z是朋友,那么x和z在一个朋友圈.如果x,y是朋友,那么x的朋友都与y的在一个朋友圈,y的朋友也都与x在一个朋友圈. 如下图: 代码: //找朋友圈个数 //找父亲节点 int FindRoot(int chi