目的: 解決元素分組問題
用途:1、判斷有向圖中是否產生環
2、維護無向圖的連通性,判斷兩個點是否在同乙個連通塊中
操作:1、初始化: 每個集合的parent都是自己
2、查詢: 查詢集合的parent
3、合併: 把不相連的元素合併到同乙個集合中
1、初始化
假如有編號為1, 2, 3, ..., n的n個元素,我們用乙個陣列fa來儲存每個元素的父節點(因為每個元素有且只有乙個父節點,所以這是可行的)。
一開始,我們先將它們的父節點設為自己。
var fa = make(int,n)
for i := 0; i < n; i++
2、查詢
我們用遞迴的寫法實現對代表元素的查詢:一層一層訪問父節點,直至根節點(根節點的標誌就是父節點是本身)。
要判斷兩個元素是否屬於同乙個集合,只需要看它們的根節點是否相同即可。
find = func(x int) int
return find(fa[x])
}
路徑壓縮方法
find = func(x int) int
return fa[x]
}
3、合併
合併操作也是很簡單的,先找到兩個集合的代表元素,然後將前者的父節點設為後者即可。
merge := func(i,j int)
按秩合併
merge := func(i,j int)
// x和y不在同乙個集合中,合併它們
if xfayfa else
}
同時使用路徑壓縮、按秩(rank)合併優化的程式每個操作的平均時間僅為 o(alpha (n)),
其中 alpha (n) 是 的反函式,a 是急速增加的阿克曼函式。
因為 alpha (n) 是其反函式,故 alpha (n) 在 n 十分巨大時還是小於5。
因此,平均執行時間是乙個極小的常數。
實際上,這是漸近最優演算法:fredman 和 saks 在 1989 年解釋了 omega (alpha (n)) 的平均時間內可以獲得任何並查集。
班上有n名學生。其中有些人是朋友,有些則不是。他們的友誼具有是傳遞性。如果已知 a 是 b 的朋友,b 是 c 的朋友,那麼我們可以認為 a 也是 c 的朋友。所謂的朋友圈,是指所有朋友的集合。
給定乙個n * n的矩陣m,表示班級中學生之間的朋友關係。如果m[i][j] = 1,表示已知第 i 個和 j 個學生互為朋友關係,否則為不知道。你必須輸出所有學生中的已知的朋友圈總數。
示例 1:
輸入:[[1,1,0],示例 2:[1,1,0],
[0,0,1]]輸出:2
第2個學生自己在乙個朋友圈。所以返回2。
輸入:[[1,1,0],注意:[1,1,1],
[0,1,1]]輸出:1
n 在[1,200]的範圍內。
對於所有學生,有m[i][i] = 1。
如果有m[i][j] = 1,則有m[j][i] = 1。
題解:
func findcirclenum(isconnected int) (ans int)
var find func(x int) int
find = func(x int) int
return parent[x]
} merge := func(from,to int)
for i := 0; i < n; i++
} }for i, p := range parent
} return
}
更多例題
------------恢復內容結束------------
一 並查集 Union Find Set)
如果 給出各個元素之間的聯絡,要求將這些元素分成幾個集合,每個集合中的元素直接或間接有聯絡。在這類問題中主要涉及的是對集合的合併和查詢,因此將這種集合稱為並查集。鍊錶被普通用來計算並查集.表中的每個元素設兩個指標 乙個指向同一集合中的下乙個元素 另乙個指向表首元素。鏈結構的並查集 採用鏈式儲存結構,...
演算法總結 並查集
搞了兩年acm,終於準備寫一些部落格了,總得留下點什麼。不了解並查集的話,推薦這個部落格學習,講的很有意思,當時笑出聲。下面寫一下自己的理解吧 並查集最簡單的用法,就是把不同的元素歸併到乙個集合裡。在集合裡選出乙個老大作為代表,集合裡的其他元素都是他的小弟。這樣,就可以判斷任意兩個元素是不是屬於同乙...
並查集演算法總結
並查集可以稱之為不相交集合,在處理查詢幾個元素是否在同一集合時使用並查集可以達到非常快的處理速度,並查集的思想有一點很重要,就是利用樹的思想,表示不同的不相交的集合狀態,利用根節點作為代表元素,來對整個集合的資料進行處理。並查集是一種非常精巧而實用的資料結構,主要用於處理一些不相交集合的合併問題,一...