(作者创作不易,可以点个关注和点赞吗,谢谢,也欢迎大家评论)
例子:
若某个家族人员过于庞大,要判断两个人是否是亲戚,确实很不容易。根据某个亲戚关系图,现在任意给出两个人,判断其是否具有亲戚关系。规定:x和y是亲戚,y和z是亲戚,那么x和z也是亲戚。如果x和y是亲戚,那么x的亲戚都是y的亲戚,y的亲戚也都是x的亲戚。
那么如何快速判断两个人是否是亲戚呢?
可以使用并查集快速判断两人是否有亲戚关系。
并查集是一种树形数据结构,用于处理一些不相交集合的合并及查询问题。创建并查集只需要三个步骤。
算法步骤:
1)初始化。把每个点所在集合初始化为其自身。
2)查找。查找两个元素所在的集合,即找祖宗。
3)合并。如果两个元素的集合号不同,将两个元素合并为一个集合。
我们先从简单的例子来了解并查集,例如现在有一个数组fa[1…n],其中fa[i]表示元素i所在的集合,用集合中最小的值代表集合。

其中可以看出来,不相交的集合是:{1,3,7},{4},{2,5,9,10},{6,8}
如果这时候我们把集合用一棵“有根树”来表示。
其中fa[i]=i,则i表示集合,并且是对应树的根。
如果fa[i]=j,j!=i,则j是i的父节点。
其中可以看出来,四个不同树是:{1,3,7},{4},{2,5,9,10},{6,8}
这时候查找函数:

这时候合并函数:

我们还可以优化性能。
方法:将深度小的树合并到深度大的树。

但是这样写法,合并函数其实最坏情况仍然是O(N)。
因此我们要进一步优化——在查找的时候进行压缩路径,思想:每次查找的时候,如果路径太长,就修改路径信息,方面下次查找。

因为每次查找都能压缩路径,所以在合并操作中,直接调用查找函数以及进行判断即可。

下面给大家布置2道题目:
【编程入门】是不是亲戚
若某个家族人员过于庞大,要判断两个是否是亲戚,确实还很不容易,现在给出某个亲戚关系图,求任意给出的两个人是否具有亲戚关系。
规定:x和y是亲戚,y和z是亲戚,那么x和z也是亲戚。如果x,y是亲戚,那么x的亲戚都是y的亲戚,y的亲戚也都是x的亲戚。
输入格式
第一行:三个整数n,m,p,(n<=5000,m<=5000,p<=5000),分别表示有n个人,m个亲戚关系,询问p对亲戚关系。
以下m行:每行两个数Mi,Mj,1<=Mi,Mj<=N,表示Mi和Mj具有亲戚关系。
接下来p行:每行两个数Pi,Pj,询问Pi和Pj是否具有亲戚关系。
输出格式
P行,每行一个’Yes’或’No’。表示第i个询问的答案为“具有”或“不具有”亲戚关系。
输入/输出例子1
输入:6 5 3
1 2
1 5
3 4
5 2
1 3
1 4
2 3
5 6
输出:Yes
Yes
No
样例解释
无
【模板】并查集
如题,现在有一个并查集,你需要完成合并和查询操作。
输入格式

输出格式

输入/输出例子1
输入:
4 7
2 1 2
1 1 2
2 1 2
1 3 4
2 1 4
1 2 3
2 1 4
输出:
NO
YES
NO
YES
样例解释

1502

被折叠的 条评论
为什么被折叠?



