并查集学习笔记

来源:互联网 发布:js初始化数组 编辑:程序博客网 时间:2024/04/28 06:37

并查集简单的说就是把一个集合的元素用一个标号来表示,每个节点的最终祖先节点就标记为这个标号。

并查集有三个操作:初始化,合并,查询。

上述为简单的朴素的并查集,不带任何的优化

chushihua(int n)根据名字也可以看出是初始化函数,也可以看出我的英语很烂,:-)。初始化的时候将每个节点的父节点设为本身,构造一群指向自己的节点的集合;

Max_size设置的是节点的个数,father数组记录的是节点父节点,初始为指向自己。

psfind()传入一个节点的标号,根据标号来寻找其属于集合的标号。找到节点的父节点的标号是其本身就是这个集合的标号,即根节点。

psunion(int root1,int root2)传入连个节点root1,root2,找到两个节点属于的集合标号,然后当不相等的时候合并两个结合就可以了,至于怎么合并,只要把一个节点的标号设置为另一个节点就可以了。

以上就是一个朴素的并查集,不带任何的优化的,当一个集合所形成的树是一个偏的很厉害的树,形成一个链状的树(所有节点都是在父节点的左链上)。每次寻找都是很浪费时间的。对n个节点的寻找的复杂度达到O(n^2)的。

下面我们来看两个优化:

1:rank数组的引入,启发式函数

2:路径压缩;

以上就是带有两个优化的代码;

当没次查询节点的标号的时候,不是找到了就大功告成了,而是把这条路径上的所有的节点的标号就OK了,复杂度接近线性的好像接近O(5*n),是个函数乘以N,细致的算法复杂度分析黑书上都是有的。

rank数组记录的是一个集合形成树的深度,合并的时候把深度小的根节点的父节点设为深度大的那个根节点就OK了的。

貌似并查集简单的就这些了。

http://zh.wikipedia.org/w/index.php?title=%E5%B9%B6%E6%9F%A5%E9%9B%86&variant=zh-cn这个是维基百科关于并查集的东东。

下面给几道简单的推荐题,让大家练下手,实践是唯一的真理呀。。。。

稍后我会写上这些题目的自己做的思路和解题报告,欢迎指教;

http://162.105.81.212/JudgeOnline/problem?id=1703

http://162.105.81.212/JudgeOnline/problem?id=2421

http://162.105.81.212/JudgeOnline/problem?id=2492

http://162.105.81.212/JudgeOnline/problem?id=1861

http://162.105.81.212/JudgeOnline/problem?id=1308

http://162.105.81.212/JudgeOnline/problem?id=2524

原创粉丝点击