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的螞蟻在一起。現在問題來了,他現在只有...