一種可以動態維護若干個不重疊的集合或無向圖的連通塊的資料結構。
主要支援以下操作:
find: 查詢乙個元素屬於哪個集合
merge: 合併兩個集合
並查集的每個集合都需要乙個「爹」來表示這整個集合,所以判斷兩個元素是否在同一集合,就看他們爹是否相同。
有乙個顯而易見的初始化,對於要維護的序列,初始每個元素的爹就是他自己,也就是初始化。
inline void init(int這裡直接放上找爹函式,也就是find操作,遞迴完成n)
inline int findfa(int考慮這樣的情況x)
畫的好醜
是不是在找 $7$ 的爹的時候要好久好久,這顯然是不能接受的。
這就要用到路徑壓縮了,怎麼壓呢?
相信聰明的你已經明白了
我們在合併的時候直接連到爹上去,順便查詢的時候也直接連上去,就ok啦。
也就是說
fa[findfa(x)] = findfa(y);我們把每個集合看成乙個樹,記錄乙個 $siz$陣列維護樹的深度,每次將深度小的合併到深度大的,這樣可以保證樹的最大深度為 $logn$ 這種方法不會破壞樹的結構,對於以後學習的撤銷操作和可持久化有益。。
觀察這兩顆樹,顯然將$1$接到$4$下面,樹的深度不會增大,但將$4$接到$1$下面,樹卻變深。
當然了,按秩合併順便路徑壓縮也是可以的,並且很快
inline void merge(int x,int初始的時候 $siz$ 都為 $1$ 。y)}
並查集(路徑壓縮 按秩合併) 總結
就是連邊,然後,每次問你兩個點是否可互通。為無向邊 然後,暴力的話可能就是一條鏈下來,搞爆了。所以我們要想想優化。個人覺得這個比較好理解,很早便學會了,而且速度要優秀一些。就是將連了邊的同時指向乙個人 自擬的祖宗 然後,每次查詢的時候就壓縮一下路徑。具體是這樣來搞的 intgf int x intm...
並查集模板 (路徑壓縮 秩的合併)優化
void init int findroot int x return findroot pre x 否則一直往上找,找其最頂層的根結點 遞迴方式 int findroot int x return pre x findroot pre x 否則一直往上找,找其最頂層的根結點,並將路徑上的關聯點都加...
資料結構之並查集 按秩合併與路徑壓縮優化
1.並查集描述 一些有n nn個元素的集合應用問題中,我們通常是在開始時讓每個元素構成乙個單元素的集合,然後按一定順序將屬於同一組的元素所在的集合合併,其間要反覆查詢乙個元素在哪個集合中。為了快速解決這些問題,便有了並查集的概念。並查集維護了乙個不相交的動態集的集合s1,s2,sns1 s2 sn ...