不管後面寫了啥,一定要把最重要的寫在前面:(總記不住)
使用陣列表示並查集:
int father[n]
;
father[i]
表示元素i
的父親結點
初始情況下,每個元素都是單獨的集合,因此其父結點是自己,這在並查集中被稱為reflexive
for
(int i =
1; i <= n; i++
)
乙個集合中只有乙個根結點,因此反覆地查詢父結點,直到father[x] == x
,則x
為該集合的根節點。
將兩個集合合併在一起,只需要找到兩個集合的根,將其中乙個根的父結點設為另乙個根即可。因為和 c/c++ 中的union
關鍵字衝突,所以函式寫成了uni
。
void
uni(
int a,
int b)
並查集有一些基礎的常規操作,為了縮短在程式設計考試中減少對「常規」操作的思考時間(雖然也很簡單),故記錄下來,形成自己習慣性的模板**。
題目中常常給定的元素編號是連續的,通常是1~n,因此可以直接將物件 id 作為下標,表示其在並查集中的位置,但是有時候給定的是字串,或是給定的範圍很大,這個時候需要對每個元素重新編號,最好的方式是從序號1開始,用兩個map分別做 id->num 和 num->id 的對映。
int
main()
if(idtonum[b]!=0
) tb = idtonum[b]
;else
uni(ta, tb)
;// 合併 ta、tb}.
....
..}
有時候題目給定了元素的編號,並且這個編號在合理的範圍內,但是編號不連續,因為並查集建立完成後需要遍歷所有元素以找出不同集合,所以,如果是不連續的元素編號則可以使用unordered_set
記錄輸入的元素,之前想過用vector
但是可能出現重複輸入一樣的編號,所以不適用。
unordered_set<
int> s;
string a, b;
while
(t--
)for
(auto it : s)
在並查集建立好之後,需要找出各個集合對之做操作。
for
(int i =
1; i < pos; i++
)
有時候需要將乙個集合作為乙個結構去看,其中需要儲存一些題目要求的資料,並做排序。則要用到 map 和 vector
struct node ;.
....
.map<
int, node> mp;
for(
int i =
1; i < pos; i++
)vector ans;
for(
auto it : mp) ans.
push_back
(it.second)
;sort
(ans.
begin()
, ans.
end(
), cmp)
;
並查集 並查集
本文參考了 挑戰程式設計競賽 和jennica的github題解 陣列版 int parent max n int rank max n void init int n int find int x else void union int x,int y else 結構體版 struct node ...
並查集學習筆記
並查集是一種用來管理資料分組狀況的資料結構,可以進行合併操作,但無法進行分割。並查集的結構 並查集也是用樹形結構來實現的,但不是二叉樹。每個資料,元素對應乙個節點,每個組對應一棵樹。並查集的實現 並查集有幾個基本操作初始化 查詢樹的根 合併x,y所屬集合 判斷x,y是否屬於同一集合。查詢是查詢樹的根...
並查集 學習筆記
並查集是由一組互不相交的集合組成的乙個集合結構,並在此集合上定義了運算union和find。即並查集中的元素本身是集合,他們是某個集合的子集,並查集是由這些集合組成的集合結構。並查集上有兩個最基本的運算,find和union。函式find搜尋給定元素i所在的子集合,並返回該自己喝 union運算將兩...