資料結構 並查集
並查集(union-find set):
一種用於管理分組的資料結構。它具備兩個操作:(1)查詢元素a和元素b是否為同一組 (2) 將元素a和b合併為同一組。
注意:並查集不能將在同一組的元素拆分為兩組。
並查集的實現:
用樹來實現。
使用樹形結構來表示以後,每一組都對應一棵樹,然而我們就可以將這個問題轉化為樹的問題了,我們看兩個元素是否為一組我們只要看這兩個元素的根是否一致。顯然,使用樹形結構將問題簡單化了。合併時是我們只需要將一組的根與另一組的根相連即可。
並查集的核心在於,一棵樹的所有節點根節點都為乙個節點。使用find函式查詢時,也是查詢到這個節點的根節點。
一行並查集:
int find(int x)
實現:
int node[i]; //每個節點
//初始化n個節點
void init(int n)
} //查詢當前元素所在樹的根節點(代表元素)
int find(int x)
//合併元素x, y所處的集合
void unite(int x, int y)
//判斷x,y是屬於同乙個集合
bool same(int x, int y)
} //查詢當前元素所在樹的根節點(代表元素)
int find(int x)
//合併元素x, y所處的集合
void unite(int x, int y)else
} //判斷x,y是屬於同乙個集合
bool same(int x, int y)
例項分析:在乙個社群裡,每個人都有自己的小圈子,還可能同時屬於很多不同的朋友圈。我們認為朋友的朋友都算在乙個部落裡,於是要請你統計一下,在乙個給定社群中,到底有多少個互不相交的部落?並且檢查任意兩個人是否屬於同乙個部落。
輸入格式:
輸入在第一行給出乙個正整數n(<= 104),是已知小圈子的個數。隨後n行,每行按下列格式給出乙個小圈子裡的人:
k p[1] p[2] ... p[k]
其中k是小圈子裡的人數,p[i](i=1, .., k)是小圈子裡每個人的編號。這裡所有人的編號從1開始連續編號,最大編號不會超過104。
之後一行給出乙個非負整數q(<= 104),是查詢次數。隨後q行,每行給出一對被查詢的人的編號。
輸出格式:
首先在一行中輸出這個社群的總人數、以及互不相交的部落的個數。隨後對每一次查詢,如果他們屬於同乙個部落,則在一行中輸出「y」,否則輸出「n」。
輸入樣例:
4輸出樣例:3 10 1 2
2 3 4
4 1 5 7 8
3 9 6 4
210 5
3 7
10 2
yn
分析:典型並查集問題。
乙個部落對應乙個集合。 根節點數量等於部落數量。
並查集把每個部落的人連起來,記錄哪些人出現過,列舉標號10000,找出有多少人和部落,查詢並查集維護。
原始碼分析:
#include #include #include #include using namespace std;
int pre[10005];
int f[10005];
void init()
int find(int x)
int main()
} int cnt=0,tot=0; //cnt為所有人數 tot為部落數量
for(int i=0; i<10004; i++)
} cout<>q;
for(int i=0; i>a>>b;
if(find(a) == find(b)) //若兩引數 有同一根節點 說明為乙個部落。
cout<
資料結構之並查集
並查集 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 如...