查並集Disjoint Set(不相交的集合)

2021-10-18 16:41:15 字數 4491 閱讀 5314

wa了好多次

常見兩種操作:

1、合併兩個集合

2、查詢某個元素屬於哪個集合

實現方法一(常用): 每個集合用一棵「有根樹」表示

1、定義陣列set[1,n];

2、set[ i ] = i ;則 i 表示本集合,並使集合對應樹的根

3、set[ i ] = j ;若 j 不等於 i ,則 j 是 i 的父節點

舉個例子:

具體操作:

1、查:最壞情況o(n)

findx

(x)

2、並:o(1)

mergeset

(a,b)

避免最壞的情況:(一般不需要)

方法:將深度小的樹合併到深度大的樹上(深度是要另外用陣列計數的)

效果:任意順序合併後,包含k個節點的樹的最大高度不超過 lg(k);

1、查:

findx

(x)

2、並:

mergeset

(a,b)

else

if(h[a]

)set[a]

=b;else set[b]

=a;}

實現方法二(不常用):1、用編號最小的元素標記所在集合;

2、定義乙個陣列set[1,n],其中set[i]表示元素i所在的集合;

舉個例子:

set(i)12

1426

1622

i123

4567

8910則不相交集合:

,,,課件每個不相交集合的第乙個元素所對應的set(0)就為該集合中所有元素所對應的值

具體操作:

1、查:o(1)

findx

(x)

2、合併:o(n)

mergeset

(a,b)

}

並集的簡單應用1、最小生成樹

hdu 1233

題意:給出互通的兩個城市的編號,使全省任意兩個城市互通,最少還需要建設多少條道路。

典型的查並集問題

#include

#define ll long long

using

namespace std;

int s[

1010];

intfindx

(int x)

void

mergeset

(int a,

int b)

intmain()

int ans=-1

;for

(int i=

1;i<=n;i++

)printf

("%d\n"

,ans);}

return0;

}

hdu 1233

典型的最小生成樹-[查並集的簡單應用]

題中的:得到的統計表中列出了任意兩村莊間的距離

說明了給的資料一定能形成最小生成樹

#include

#define ll long long

using

namespace std;

//最小生成樹問題

int s[

110]

;struct node c[

5000];

bool

cmp(node x,node y)

intfindx

(int x)

intmain()

}printf

("%d\n"

,ans);}

return0;

}

hdu 1863

題中的:統計表中列出了有可能建設公路的若干條道路的成本

說明了不一定能形成最小生成樹(即不能暢通輸出 「?」),且 m<= sum(1+2+```+n-1)=n*n/2=5000;

不能生成最小數的判斷有兩個方法:

法一:遍歷每個根節點出現不同則不能生成:有兩種實現方式

方式①:

#include

#define ll long long

using

namespace std;

//最小生成樹問題

int s[

110]

;struct node c[

5010];

bool

cmp(node x,node y)

intfindx

(int x)

intmain()

}bool f=0;

for(

int i=

2;i<=m;i++

)//判斷根節點是否都相同}if

(f)printf

("?\n");

else

printf

("%d\n"

,ans);}

return0;

}

方式②:

#include

#define ll long long

using

namespace std;

//最小生成樹問題

int s[

110]

;struct node c[

5010];

bool

cmp(node x,node y)

intfindx

(int x)

intmain()

}for

(int i=

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

(cnt==1)

printf

("%d\n"

,ans)

;else

printf

("?\n");

}return0;

}

法二:搜完那些資料以後,能構成的邊小於m-1

#include

#define ll long long

using

namespace std;

//最小生成樹問題

int s[

110]

;struct node c[

5010];

bool

cmp(node x,node y)

intfindx

(int x)

intmain()

}if(g

printf

("?\n");

else

printf

("%d\n"

,ans);}

return0;

}

hdu 1272

題意:構成乙個「聯通的圖」且不能有環

wa了好多發的原因:

1、我以為這個題僅僅只是沒有環,直接找兩點的根是否相同就行,但是!!!沒注意到是構成乙個圖,也就是說,還得判斷根有幾個

2、輸入是0 0的時要輸出yes

3、輸出的yes和no的大小寫,最後幾發被這個貢獻了他竟然不是pe。

#include

using

namespace std;

int s[

100010

],v[

100010];

intfindx

(int x)

intmain()

for(

int i=

1;i<=

100000

;i++

)

v[a]=1

;v[b]=1

;s[a]

=b;int x,y,cnt=

0,g=0;

bool f=0;

while

(scanf

("%d%d"

,&x,

&y))

if(f)

printf

("no\n");

else

if(g==1)

printf

("yes\n");

else

printf

("no\n");

}}return0;

}

並查集(disjoint set)的實現及應用

這裡有一篇十分精彩 生動的 並查集詳解 disjoint set,並查集 一種集合 也叫不相交集,同時也是一種樹型的資料結構 用於處理一些不相交集合 disjoint sets 的合併 merge 及查詢 find 問題。常常在使用中以森林來表示。集就是讓每個元素構成乙個單元素的集合,也就是按一定順...

並查集 並查集

本文參考了 挑戰程式設計競賽 和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 ...

並查集入門(普通並查集 帶刪除並查集 關係並查集)

什麼是並查集?通俗易懂的並查集詳解 普通並查集 基礎並查集 例題 題解 how many tables problem description lh boy無聊的時候很喜歡數螞蟻,而且,還給每乙隻小螞蟻編號,通過他長期的觀察和記錄,發現編號為i的螞蟻會和編號為j的螞蟻在一起。現在問題來了,他現在只有...