動態連通性 union find演算法

2021-09-24 04:16:34 字數 2324 閱讀 1384

等價關係:定義(p,q)表示p與q相連,是一種等價關係,具有自反性,對稱性以及傳遞性。

等價關係定義了等價類,給定多個整數對,判斷其是否屬於同一類,即是否具有動態連通性。

從集合的角度在處理(p,q)時,判斷其是否屬於不同的集合,如果屬於不同的集合則將p以及p所屬的集合進行合併。

給定多個整數對,可以確定多個動態連通分量,定義資料結構

利用陣列id來表示每個元素所在的分量id,判斷兩個元素p,q是否屬於同一分量,則判斷id[p]==id[q]即可。

//某個元素所在分量序號

public int find(int p)

public boolean connected(int p, int q)

當執行union操作時,如果屬於不同分量,則將p所在分量的所有元素id分量索引全部改為p所在分量id

//如果p,q處於不同分量中,則將p,q分量合併,將p所在分量所有元素改為q分量id

//合併union效能糟糕

public void union(int p, int q)

id陣列變化如下所示:

[0, 1, 2, 3, 4]

[1, 1, 2, 3, 4]

[2, 2, 2, 3, 4]

[3, 3, 3, 3, 4]

[4, 4, 4, 4, 4]

quick-find演算法union方法效能糟糕,進行改進。將id陣列看成是父連線陣列,即對於x來說,id[x]=p,表示p與x處於同一分量中。

find方法根據p=id[p]不斷尋找,直到找個某個根節點

//某個元素所在分量根元素序號

public int find(int p)

return p;

}

union合併方法,則首先找到兩個元素的根節點,如果根節點不同,則將p所在根節點指向q所在根節點

實際上id陣列儲存多顆樹,每個分量利用父連線組織成一棵樹,利用樹的根節點來表示某個元素所在的分量

//如果p,q處於不同分量中,則將p,q分量合併

//合併演算法效率較高 但是find效率較低

public void union(int p, int q)

**如下:

public class quickunionuf {

//同乙個分量中另一元素的名稱 例如id[p]=x表示p與x處於同一分量

//id陣列用父連線表示一片森林

private int id;

//分量數量

private int count;

//初始化n個元素n個分量

public quickunionuf(int n) {

count = n;

id = new int[n];

for(int i=0; iunion會將兩個樹不斷合併,最壞情況下,樹會蛻變成煉表,導致find演算法查詢效率低下。

加權quick-union主要改進如下:在union合併兩棵樹時,將小樹合併到大樹中,避免樹的高度過度增長

利用sz陣列來儲存每顆樹的元素個數

**如下:

public class weightedquickunionuf {

//同乙個分量中另一元素的名稱

//id陣列用父連線表示一片森林

private int id;

//分量數量

private int count;

//各個根節點對應分量大小

private int sz;

//初始化n個元素n個分量

public weightedquickunionuf(int n) {

count = n;

id = new int[n];

for(int i=0; i執行union時,判斷兩個樹的元素大小,將小樹合併到大樹中,避免樹的高度過度增加,保證演算法在對數效能級別。

動態連通性

問題 一對整數p,q可以理解為 p與q是相連的 問給出一組整數對p,q,判斷p,q是否相連,如果相連,則忽略,不想連則新增連線。如 a b c d 則此時認為abcd互相連線。如果新增另一組整數對a,c 則新增不成功,因為此時a,c已經連通 若新增另一組整數對a,f。則新增成功,此時a,b,c,d,...

動態連通性問題

首先定義演算法的api 方法作用 uf int n 初始化觸點及其他資料 int find int p 返回p所在連通分量的識別符號 int union int p,int q 在p和q之間新增一條線 int count 返回連通分量的數量 boolean connected int p,int q...

並查集,動態連通性

n,m n個點,m條邊 隨之而來m條邊 q 代表q個操作 q行,每行乙個序號,代表將第m個輸入的邊刪除,問刪除後有多少個連通塊。思路 我們將m條邊,和q詢問記錄下來,並將要刪除的邊標記。然後對那些不用的邊使用並查集,並算出有多少個連通塊。然後從最後乙個詢問開始,依次將那些邊加入並查集,如果加入時,兩...