路徑壓縮優化並查集大家一定很熟練了,那么它的復雜度是多少呢?
O(mα(n))?
的確,很多人都是這么說的,但是事實上它的復雜度是
O(mlog1+m/nn)的,並且能找到一種方法卡到這樣的復雜度。
要卡並查集,首先要構造一種樹——二項樹。這種二項樹還與普通的不太一樣。
定義:在給定
j的情況下,二項樹
Tk定義如下:
- 若
k≤j,
Tk是一個點。
- 若
k>j,
Tk是
Tk−1的根結點增加一棵
Tk−j的子樹。

這棵樹非常有意思,我們可以展開
Tk−j,接着展開
Tk−2j……
另外,也可以展開
Tk−1,接着展開
Tk−2……

容易發現,圖5看起來像圖4的路徑壓縮之后的結果,但是不完全一樣。
如果首先按照圖5的方式展開
j棵子樹,再按圖4展開,可以得到

此時,如果在根節點上再加一個點,
j次訪問
T1到
Tj,那么路徑壓縮后可以得到圖5外加一個點作為根的兒子。
也就是說,這棵二項樹路徑壓縮后約等於沒有路徑壓縮……只是將原來作為根結點父親的那個點變成了兒子。
至於
Tk的點數,通過數學歸納法可以發現不會超過
(j+1)k/j−1個。
假設
m≥n,令
j=nm,i=logj+12n+1,k=ij,那么
Tk的點數不超過
2n。接下來做
2n組操作,每次加入一個點作為根結點的父親,然后對
T1到
Tj逐個查詢,每次查詢的長度是
i+1,同時查詢的次數顯然不超過
m。因此總操作次數為
2nj(i+1),即
O(mlog1+m/nn)。
圖片取自康復計划#4 快速構造支配樹的Lengauer-Tarjan算法。