kruskal算法生成最小生成树

kurskal算法更适合稀疏图

kruskal算法伪代码:

 1 int kruskal(){
 2     令最小生成树的边权之和为ans, 最小生成树的当前边数为Num_Edge;
 3     将所有边按边权从小到大排序;
 4     for (从小到大枚举所有的边){
 5         if (当前测试边的两个端点在不同的连通块中){
 6             将测试边加入最小生成树中;
 7             ans += 测试边的边权;
 8             最小生成树的当前边数Num_Edge加一;
 9             当前边数Num_Edge等于顶点数减1是结束循环;
10         }
11 
12     }
13     return ans;
14 }

具体实现:

 1 struct edge{
 2     int u, v;            //边的两个端点编号
 3     int cost;            //边权
 4 }E[MAXV];
 5 
 6 bool cmp(edge a, edge b){
 7     return a.cost < b.cost;
 8 }
 9 int father[MAXV]; //并查集数组
10 
11 //并查集查询函数
12 int findFather(int x){
13     int a = x;
14     while (x != father[x]){
15         x = father[x];
16     }
17 
18     //路径压缩
19     while (a != father[a]){
20         int z = a;
21         a = father[a];
22         father[z] = x;
23     }
24 
25     return x;
26 }
27 
28 //kruskal函数返回最小生成树的边权之和,参数n为顶点个数, m为图的边数
29 int kruskal(int n, int m){
30     int ans = 0, Num_Edge = 0;    //最小边权之和,当前生成树的边数
31     //初始化并查集
32     for (int i = 1; i <= n; i++){
33         father[i] = i;
34     }
35 
36     //对所有边排序
37     sort(E, E + m, cmp);
38     //遍历所有的边
39     for (int i = 0; i < m; i++){
40         int faU = findFather(E[i].u);        //查询测试边两个端点所在集合的根节点
41         int faV = findFather(E[i].v);
42         if (faU != faV){
43             father[faV] = faU;
44             ans += E[i].cost;
45             Num_Edge++;
46             if (Num_Edge == n - 1) break;    //如果已经建成了一棵树,跳出循环
47         }
48     }
49     if (Num_Edge != n - 1) return -1;        //当图不连通时,返回-1
50     else return ans;        //否则返回最小生成树的边权之和
51 }

 

上一篇:JavaScript原型和原型链(详细解读)


下一篇:9.final关键字