我一直有一种观点,或是直觉,就是,越显然的事情或道理,其实若要仔细探究起来,其原理是很难证明的。并查集这个东西,很早就了解过,也学习过,也对那个金庸群像的讲解博客感到拍案叫绝。在了解了并查集算法的原理之后,发现它还是很简单的。或者说,是很好理解的。它的原理是很“显然”的,但就是这个“显然”让我很困惑:你说它显然,但是你怎么证明这个“显然”是对的呢?相信大部分人并不一定能回答这个“显然”背后的数学推导。本文就是基于博主及其浅显和薄弱的数学基础,希望看到并且学过并查集的人看到也能有一点收获。
并查集问题描述:直接粘一道经典入门题吧
hdu 1232:http://acm.hdu.edu.cn/showproblem.php?pid=1232
某省调查城镇交通状况,得到现有城镇道路统计表,表中列出了每条道路直接连通的城镇。省政府“畅通工程”的目标是使全省任何两个城镇间都可以实现交通(但不一定有直接的道路相连,只要互相间接通过道路可达即可)。问最少还需要建设多少条道路?
并查集的解法很简单:
定义pre(x):x的父亲为pre(x)
当pre(x)= x时没有父亲,即为这个小集合的根;
引入find(x)操作:查找x的根
引入join(x,y)操作:将x y所在集合合并,具体操作为 pre(find(x)) = find(y)将x的根节点接到y的根节点上;
其中,为了降低find寻找次数,在每次寻找完成之后,让所有寻找过的父节点直接指向根节点;(路径压缩)
这个算法的复杂的为o(n) 相比于暴力搜索,我更喜欢这个方法,它的时间消耗相比dfs更加可控
这个算法理解一来没有什么难度,接下来,我希望以一种基于数学的方法证明这个算法的正确性。
《离散数学》第一章有着对集合 关系颇为详尽的定义:
集合S上的关系: 设一个集合为S,它的笛卡尔积S*S的某一个子集R既是S到S的一个关系,任取R中的一个元素(x,y)称x关于R与y相关联
记作:xRy
R可能具备一些特殊的性质:
(1)对于S中任一元素x,xRx为真,则称R是自反的
(2)如果xRy为真,yRx为真,则R是对称的
(3)只要xRy为真 yRz为真,则xRz为真,则称R是传递的;
满足以上三条则R为S上等价关系
接下来引入等价类的概念:若R是S上的等价关系,对于S中任一元素x,则S中与x相关联的元素的集合成为包含x的等价类,记为[x]。
接下来引入两条定理
设R是S上的等价关系
(a)如果x和y是集合S中的元素,那么x与y相关联当且仅当[x]=[y]
(b)关系R的两个等价类要么相等,要么互不相交
则根据(b)则R的等价类可将集合S划分为一些彼此不相交的子集
这些子集称为S的划分
回到上面的那个题目。
题目中给出城市相镇两两相连,既是S中的x y相关联。以这种相关联关系得出的R,很容易证明出它是S上的一个等价关系;
所以 可以将题目翻译成:给出S集合上一些元素相关联,求S按此关系R的划分数
然后证明find 和join操作的正确性:
pre数组的值实质上就是在每一个等价类中选择一个数作为这个等价类的标记
find操作和join操作的正确性可以由等价关系性质(3)得出:
如果一个节点x指向y y指向z 根据传递性 可以得出 x指向z
同时,我们根据定理(a)(b)可以得出:不存在某一个点时属于两个不同的等价类的
这样也同时证明了结果的唯一性:由于划分的唯一,划分数唯一,不存在多解的情况
综上:并查集算法的正确性是可以保证的。
总结:上面的证明对于我们对算法本身的理解是非(mei)常(sha)有(luan)用(yong)的,它让我明白了,即使道理浅显,也需要严格的数学证明。一屋不扫,何以扫天下?——站在巨人的肩膀上,真(是超级无敌宇宙橡胶锤的)好啊