並查集演算法

2021-10-01 01:43:07 字數 3501 閱讀 4163

並查集是一種資料結構

首先,我們有一群數,1,2 3, 4, 5…1115…

每個數又有屬於他自己的集合,

例如,…

我們的任務就是判斷某兩個數是否屬於同乙個集合

我們把每個集合都可以看成是一棵樹,(不知道什麼是樹的同學可以接著往下看)

判斷兩個數是否屬於乙個集合,實際就是判斷他們的根節點是都是同乙個?

(劃重點,考試要考的)

喏,這就是一棵「樹」。

如圖,a就是這棵樹的「根節點」,如果要判斷c和d是否屬於同乙個集合,

就看c和d是否有相同的根節點。

前面說到,「就看c和d是否有相同的根節點。」

那麼我們要 先找到c和d的根節點是誰,接著才能接著判斷,你說是吧。

於是就有了關於並查集的操作

先定義乙個陣列 f [x],來儲存每個元素的父親節點。

(例如,如上圖,b是d的父親節點,c是e的父親節點。)

x的父親節點是 f [x] ,x的父親節點的父親節點是 f [ f[x] ]…

這裡就體現出了遞迴的思想,

瘋狂翻族譜中ing…

我們一直向上,找父親節點的父親節點的父親節點的父親節點父親節點的父親節點父親節點的父親節點父親節點的父親節點(滑稽)…最後找到了根節點

其實就是,我,找我的爸爸是誰,找我的爺爺是誰,找我的曾爺爺是誰,找我的曾曾曾爺爺是誰,找我的曾曾曾爺爺是誰…最後找到我們夏朝的祖先

發現我們都是炎黃子孫…所以我們是乙個集合的。

查詢操作的函式**:

int

find

(int x)

//瘋狂翻族譜中......

同乙個世界,同乙個夢想,上回說到我們都是炎黃子孫。

可是非洲東海岸的朋友們也想和我們成為有血緣關係的一家人,可是奈何我們不是乙個祖先啊。

於是我便想坐著時光機回到大約五千年前…

找到了非洲東海岸朋友們的祖先,和我們的祖先,讓他們成為一家人,

於是後世的世世代代的我們就成為了一家人。

(正經臉):

如果想合併兩個集合,那麼只需要找到他們的根節點,在兩個根節點之間「連線」,那麼這兩棵樹就成為了一棵樹。

至於是誰成為最後的根節點,這不重要,世界和平(成為乙個集合)才是我們最後想要的結果。

合併操作的函式**:

void

unionn

(int x,

int y)

1.什麼是路徑壓縮?這個聽起來很高大上的名字…

其實就是「認祖宗做爹」「一人之下萬人之上」 「一步到位」

在上面的找根節點操作函式**中,你注意到了嗎?

else

return f[x]

=find

(f[x]);

把x的祖宗find

(f[x]

),賦值給x的爸爸f[x],

這不就是認祖宗做爹嘛

可是為什麼要這麼做呢?

以前我們找根節點(祖宗),我們要瘋狂翻族譜,一層一層的向上遞迴。

現在我們只需要看一眼自己的爸爸是誰,就知道自己的祖宗是誰了,複雜度一下子變成o(1)了!

想象乙個散發光芒的太陽,中間的不就是祖先嘛,圍繞著他散發光芒的就是除了祖先之外的所有人啦!這該死的魅力!!!

完整**模板

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#define myself i,l,r

#define lson i<<

1#define rson i<<1|

1#define lson i<<

1,l,mid

#define rson i<<1|

1,mid+1,r

#define half (l+r)/2

#define lowbit

(x) x&

(-x)

#define min4

(a,b,c,d)

min(

min(a,b)

,min

(c,d)

)#define min3

(x,y,z)

min(

min(x,y)

,min

(y,z)

)#define max4

(a,b,c,d)

max(

max(a,b)

,max

(c,d)

)#define max3

(x,y,z)

max(

max(x,y)

,max

(y,z)

)typedef long

long ll;

const

int inff=

0x3f3f3f3f

;const

double eqs=

1e-9

;const

double e=

2.718281828459

;const

double pi=

acos(-

1.0)

;using namespace std;

const

int maxn=

1005

;int f[maxn]

;int

find1

(int x)

intfind

(int x)

void

unionn

(int x,

int y)

intmain()

int ans=0;

for(

int i=

1;i<=n;i++)if

(find

(i)==i) ans++

; cout<

1<

}}

並查集演算法

所謂並查集,它是乙個集合,這個集合的元素也是集合,他支援三種操作 makeset x 建立乙個只有乙個元素x的集合x0,將這個集合放入並查集中 findset x 在並查集中尋找乙個元素s 注意並查集的元素s也是集合 滿足 x屬於s union x,y 將並查集中的元素s1,s2合併,其中x屬於s1...

並查集演算法

並查集是一種樹型的資料結構,用於處理一些不相交集合 disjoint sets 的合併及查詢問題。常常在使用中以森林來表示。讓每個元素構成乙個單元素的集合,也就是按一定順序將屬於同一組的元素所在的集合合併。1 makeset s 建立乙個新的並查集,包含s個單元素集合。2 union x,y 把x ...

並查集演算法

includeint pre 10 int find int x 查詢祖先節點 int i x,j while i r 壓縮路徑 return r void join int x,int y int main 2 食物鏈問題 description 動物王國中有三類動物a,b,c,這三類動物的食物鏈...