1.並查集是一種樹形的資料結構,顧名思義,它用於處理一些不交集的合併及查詢問題。 它支援兩種操作:
查詢(find):確定某個元素處於哪個子集;
合併(union):將兩個子集合並成乙個集合。
初始化
void
makeset
(int size)
查詢
int
find
(int x)
合併
void
unionset
(int x,
int y)
2.優化並查集
顯然查詢效率實在太低。為什麼呢?因為我們使用了太多沒用的資訊,我的祖先是誰與我父親是誰沒什麼關係,這樣一層一層找太浪費時間,不如我直接當祖先的兒子,問一次就可以出結果了。甚至祖先是誰都無所謂,只要這個人可以代表我們家族就能得到想要的效果。 把在路徑上的每個節點都直接連線到根上 ,這就是路徑壓縮。
int
find
(int x)
以上就是最基本的並查集,而在題目中往往不會如此出題
例如2020多校第二場1001簽到題
題目大意:給你n個房子,每個房子m的亮度,再給你一些可以聯通的房子的序號,每次你選擇一些聯通的房子亮度全部減一。直到所有房子亮度為0(亮度為0的房子不可再選擇)
求最少的運算元
思路:暴力
明顯選擇每次最大的連通塊,減到不能減後**成小連通塊,再繼續選擇最大連通塊是可以得到正確結果的,但是在刪除亮度為0的房子時,並查集就難以維護了(反正我不會)
再思考,當把從最大連通塊開始進行暴力操作後,留下的小連通塊是更亮的,於是我們可以反過來思考,從最亮的房子(x)開始判斷 ,依次遍歷這個房子所能夠聯通的房子(y),如果 y 在 x 之前加入且 x 和 y 不連通則將 x 和 y 合併(此時y的樹根亮度減去x亮度,因為把x加入這個連通塊就多操作了x次),並將 y 所在連通塊的樹根的父親設為 x(x成為這個連通塊的新樹根)這樣我們就可以算出每乙個點對答案的貢獻,最後把所有貢獻加一遍就好了
主要**如下
ll res =0;
for(
int i =
1; i <= n;
++i)
} isf[house[i]
.id]=1
;}for(
int i =
1; i <= n;
++i) res +
= light[i]
;
注意用vector存邊後,記得清除vector。
就這樣簽到題寫完了
並查集描述及**出自於
oiwiki
並查集入門
簡述 其實並查集顧名思義就是有 合併集合 和 查詢集合 兩種操作的關於資料結構的一種演算法。並查集演算法不支援分割乙個集合。演算法 用集合中的某個元素來代表這個集合,該元素稱為集合的代表元。乙個集合內的所有元素組織成以代表元為根的樹形結構。對於每乙個元素 parent x 指向x在樹形結構上的父親節...
並查集入門
簡述 其實並查集顧名思義就是有 合併集合 和 查詢集合 兩種操作的關於資料結構的一種演算法。並查集演算法不支援分割乙個集合。演算法 用集合中的某個元素來代表這個集合,該元素稱為集合的代表元。乙個集合內的所有元素組織成以代表元為根的樹形結構。對於每乙個元素 parent x 指向x在樹形結構上的父親節...
並查集入門(普通並查集 帶刪除並查集 關係並查集)
什麼是並查集?通俗易懂的並查集詳解 普通並查集 基礎並查集 例題 題解 how many tables problem description lh boy無聊的時候很喜歡數螞蟻,而且,還給每乙隻小螞蟻編號,通過他長期的觀察和記錄,發現編號為i的螞蟻會和編號為j的螞蟻在一起。現在問題來了,他現在只有...