生成树--Kruskal

今天心血来潮,写这篇关于算法的文章,,

也因为我家的dog来问我这玩意是什么,

于是乎,我便写这篇文章来复习复习,,

最小生成树:

一个有 n 个结点的连通图的生成树是原图的极小连通子图,且包含原图中的所有 n 个结点,并且有保持图连通的最少的边。最小生成树可以用克鲁斯卡尔算法或普里姆算法求出。

不过我一般还是用克鲁斯卡尔多一点(好写),

克鲁斯卡尔的描述:

1)将原数组排序,从大到小(最大生成树),从小到大(最小生成树)。

2)按排序后数组一次判断,两端是否在同一集合中(并查集),若不是,加入生成树中[边数到达,或遍历完成结束]。

3)一不小心做完了。

这是有关描述,然后来说说例子(最小生成树),

有数据:

A-B 10

A-C 5

B-C 15

C-D 20

B-D 30

排序可得: 

A-C 5

A-B 10

B-C 15

C-D 20

B-D 30

由于A,C不在同一集合中,加入这条边,

由于A,B不在同一集合中,加入这条边,

由于B,C在同一集合中,不用加,

由于C,D不在同一集合中,加入这条边,边数到达,结束。

附上代码:

 1 struct Edge{
 2     int fm,to,dist;
 3 }e[MAXN_E];
 4 bool cmp(Edge a,Edge b)
 5 {
 6     return a.dist < b.dist;
 7 }
 8 int getfa(intx){
 9     if(fa[x]!=x) fa[x] = getfa(fa[x]);
10     return fa[x];
11 }
12 int same(int x,int y){
13     return getfa(x)==getfa(y);
14 }
15 void merge(intx,inty)
16 {
17     int fax=getfa(x),fay=getfa(y);
18     fa[fax]=fay;
19 }
20 void kruckal()
21 {
22     sort(e+1,e+m+1,cmp);
23     for(int i=1;i<=n;i++)
24     fa[i]=i;
25     int rst=n,ans=0;
26     for(int i=1;i<=m && rst>1;i++)
27     {
28         int x=e[i].fm,y=e[i].to;
29         if(same(x,y)) continue;
30         else
31         {
32             merge(x,y);
33             rst--;
34             ans+=e[i].dist;
35         }
36     }
37 }
View Code

 



 

posted @ 2016-10-13 22:37  SXia  阅读(158)  评论(0编辑  收藏  举报