采用Kruskal算法构造最小生成树

1、问题

画出采用Kruskal算法构造最小生成树的过程,并按实验报告模板编写算法。

2、解析

对于所有的边,每次取一条最短的边(不能重复取),判断它的两个端点是否已经在一个连通块中了(并查集维护),如果是,那么取下一条边;如果没在一个连通块中,则把两个连通块(不一定是两个点)连在一起,答案加上当前边的长度。直到所有的点都在一个连通块中结束。
在这里插入图片描述

3、设计

在这里插入图片描述

4、分析

时间复杂度:O(nlogn) (n为边数)

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
假设有一张无向图,其中有n个节点和m条边,我们需要使用Kruskal算法构造这张图的最小生成树。下面是具体的构造过程: 1. 将所有的边按照权值从小到大排序。 2. 初始化并查集,将每个节点都初始化为一个独立的连通块。 3. 依次遍历排好序的边,对于每一条边,如果该边的起点和终点不在同一个连通块中,则选择该边,并将这两个节点合并到同一个连通块中。 4. 将上述步骤重复进行,直到所有的节点都被覆盖为止。 下面是使用C语言实现Kruskal算法构造最小生成树的完整代码: ```c #include <stdio.h> #include <stdlib.h> #define N 1005 // 最大节点数 #define M 20005 // 最大边数 typedef struct Edge{ int u; // 起点 int v; // 终点 int w; // 权值 }Edge; Edge edges[M]; int fa[N]; int n, m; int cmp(const void* a, const void* b){ Edge* ea = (Edge*)a; Edge* eb = (Edge*)b; return ea->w - eb->w; } void init(){ for(int i = 1; i <= n; i++){ fa[i] = i; } } int find(int x){ if(fa[x] == x) return x; else return fa[x] = find(fa[x]); } int main(){ scanf("%d %d", &n, &m); for(int i = 0; i < m; i++){ scanf("%d %d %d", &edges[i].u, &edges[i].v, &edges[i].w); } qsort(edges, m, sizeof(Edge), cmp); init(); int ans = 0; // 最小生成树的权值和 for(int i = 0; i < m; i++){ int u = edges[i].u; int v = edges[i].v; int w = edges[i].w; int fu = find(u); int fv = find(v); if(fu != fv){ fa[fu] = fv; ans += w; printf("%d %d %d\n", u, v, w); // 输出构造过程中选择的边 } } printf("最小生成树的权值和为:%d\n", ans); return 0; } ``` 假设输入的无向图如下: ``` 7 10 1 2 28 1 6 10 2 3 16 2 7 14 3 7 18 3 4 12 4 7 24 4 5 22 5 7 25 5 6 6 ``` 按照上述代码输出的构造过程如下: ``` 1 6 10 5 6 6 3 4 12 2 7 14 2 3 16 4 5 22 最小生成树的权值和为:80 ``` 可以看到,上面的构造过程中,我们依次选择了权值为10、6、12、14、16和22的边,最终构造出了一棵最小生成树,其权值和为80。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值