並查集到帶權並查集
\space \space\space \space\space \space\space \space\space \space\space \space我們為什麼要學習帶權並查集呢?我們知道,對於普通並查集而言,它反映的是集合與集合之間的關係(即元素是否處於這個集合),相當於是乙個無權圖,而集合內元素之間的關係並沒有表明。如果我們一旦想體現出集合中元素之間的相互關係,即邊權值,那麼普通並查集必然不能實現,所以帶權並查集就出來了。它不僅記錄集合的關係,還記錄著集合內元素的關係或者說是集合內元素連線線的權值。 這個本質實際上就是乙個帶權圖。
那麼,我們如何考慮權值呢?在普通並查集中只有兩種操作,一種是路徑壓縮尋找根節點,一種是合併操作。 要知道,每個節點記錄的是與父節點邊的權值。那麼在路徑壓縮過程中,我們對權值也應該進行相應的更新。因為在路徑壓縮之前,每個節點都是與其父節點鏈結著,那個權值自然也是與其父節點之間的權值,而路徑壓縮之後,父節點早已改變成根節點,這是我們最值得注意的一步操作,這也是帶權並查集最難理解的地方。在合併操作中同樣如此,我們需要將兩個節點連線起來,那麼乙個節點的父節點自然改變了,我們同樣也要進行權值更新。
\space \space\space \space\space \space
所以我們需要在普通並查集的基礎上新增乙個val
uevalue
valu
e陣列來表示
這裡我們如何更新權值呢?我們想想,我們在未進行路徑壓縮之前,是這樣的乙個情況:a
−>b−
>c−
>d−
>
ea->b->c->d->e
a−>b−
>c−
>d−
>
e,假設e
ee就是根節點,我們需要從a
aa點開始進行路徑壓縮,而每個節點它們的權值只是到它們當前父節點的權值。 我們要的是每個節點的父節點都是根節點,那麼權值也是與根節點的權值。故這裡我們需要如何處理呢?我們看直接與根節點e
ee相連的d
dd點,這個d
dd點的權值自然是沒有必要更新,就是val
ue[d
],value[d],
value[
d],那麼c
cc點呢?它所要進行的更新操作是不是val
ue[c
]=va
lue[
c]+v
alue
[d]value[c]=value[c]+value[d]
value[
c]=v
alue
[c]+
valu
e[d]
,而b
bb點呢?若c
cc點的權值已經更新,即說明c
cc點是與根節點e
ee相連,那麼是不是也是一樣的方法,直接加上上乙個點的權值即可。所以我們發現了什麼,這是乙個遞迴的過程,先尋找到根節點,再回溯更新權值 和根節點。 故非遞迴版路徑壓縮在這裡是不太好用的,我們使用遞迴版路徑壓縮。具體看**。
int
find
(int x)
else
}
已知x,y根節點分別為xroot,yroot,如果有了x、y之間的關係,合併如果不考慮權值直接修改father就行了,但是現在是帶權並查集,必須得求出xroot與yroot這條邊的權值是多少,很顯然x到yroot兩條路徑的權值之和應該相同,就不難得出上面**所表達的更新式。我們來看幾張圖。那麼合併操作就很好寫了,我們來看**。
這就是帶權並查集,當然,用起來可並不是這麼簡單,我們怎麼去表示這個權值這是乙個問題,不要套模板,得用心去體會,才是解題之道。int xroot =
findset
(x);
int yroot =
findset
(y);
if(xroot != yroot)
並查集,帶權並查集
題意 ignatius過生日,客人來到,他想知道他需要準備多少張桌子。然而一張桌子上面只能坐上相互熟悉的人,其中熟悉可定義成為a與b認識,b與c認識,我們就說a,b,c相互熟悉 例如a與b熟悉and b與c熟悉,d與e熟悉,此時至少需要兩張桌子。輸入 t表示樣例個數,n表示朋友個數,朋友從1到n編號...
帶權並查集
食物鏈 time limit 1000ms memory limit 10000k total submissions 71395 accepted 21146 description 動物王國中有三類動物a,b,c,這三類動物的食物鏈構成了有趣的環形。a吃b,b吃c,c吃a。現有n個動物,以1 n...
帶權並查集 then
問題 b 便 時間限制 2 sec 記憶體限制 512 mb 提交 50 解決 14 題目描述 給出乙個r c的棋盤.共有r行c列,r c個格仔.現要在每個格仔都填乙個非負整數.使得任意乙個2 2的正方形區域都滿足這樣的性質 左上角的數字 右下角的數字 左下角的數字 右上角的數字.有些格仔已經確定,...