並查集是一種用來管理元素分組情況的資料結構。並查集可以高效地進行如下操作。不過需要注意並查集雖然可以進行合併操作,但是卻無法進行分割操作。
n個城市中(編號1~n),有一些城市間會有無向的通路。
現在小明想從a城市到b城市,判斷是否能實現?即a和b是否有直接或間接的道路連通起來。
如有4個城市,其中1和2有道路,3和4有道路。
那麼1 2可以相通,3 4可以相通,其他情況均不行。
簡單的思考可以發現,如果我們把有通路的記為同一堆,只需判斷a和b是否在同一堆裡即可。
所以我們現在要實現的就是維護他們之間的連通關係。
為了查詢的方便,我們用一堆裡面的某乙個城市當作這個堆的代表(老大),我們判斷a和b即判斷他們的老大是否相同。這個老**擇誰其實是無所謂的,我們一般用這個堆裡面的第乙個元素就當這個堆的老大。
現在我們來看看到底如果操作
主要說明元素的查詢和合併
查詢之前我們需要把每乙個pre[x]初始化,表示它自己就是他所在堆的老大
for
(int i=
1;i<=n;i++
) pre[i]
=i;
我們用pre[x]表示x的上級(不一定是老大)一直向上找,直到pre[x]=x就可以知道x就是x所在堆的老大
int
findroot
(int x)
但這樣有乙個弊端,就是同乙個x會被查詢很多次,所以我們可以用乙個小技巧,用pre[x]來記錄它盡量上級的乙個上級
int
findroot
(int x)
這樣我們就維護可以查詢到x的老大是誰,如果有一條路把x和y連起來了,那麼我們就需要把x和y所在的兩個堆合併起來。
其中的x和y分別是兩個堆的root
void
mix(
int x,
int y)
牛客14685
/*
* @description:
* @autor: kadia
* @date: 2020-06-01 18:23:52
* @lasteditors: kadia
* @lastedittime: 2020-06-01 20:01:29
* nk
*/#include
using
namespace std;
int pre[
100005];
intfindroot
(int x)
void
mix(
int x,
int y)
intmain()
} cout <<
--all << endl ;
return0;
}
資料結構之並查集
並查集 union find sets 是一種簡單的用途廣泛的集合.並查集是若干個不相交集合,能夠實現較快的合併和判斷元素所在集合的操作,應用很多,如其求無向圖的連通分量個數 最小公共祖先 帶限制的作業排序,還有最完美的應用 實現kruskar演算法求最小生成樹。其實,這一部分 演算法導論 講的很精...
資料結構之並查集
覺得很不錯的參考資料引用一下 陣列實現 合併操作代價高,可達o n 2 鍊錶實現 樹結構實現 查詢與合併的平均時間複雜度為o log 2 n 與樹的深度有關,優化 降低時間複雜度 按秩合併 若h b h b,則將b樹作為a樹的子樹。帶路徑壓縮的查詢演算法 改變結點所指方向以減小深度,查詢路徑時 走兩...
資料結構之並查集
1.將兩個集合合併。2.詢問兩個元素是否在乙個集合當中。複雜度近乎o 1 基本原理 每個集合用一棵樹來表示。樹根的編號就是整個集合的編號。每個節點儲存它的父節點,p x 表示x的父節點。問題1 如何判斷樹根 if p x x 問題2 如何求x的集合編號 while p x x x p x 問題3 如...