Kruskal算法求最小生成树

AcWing 859

题目传送门
前置芝士

最小生成树的定义:

给定一张边带权的无向图 G=(V,E),其中 V 表示图中点的集合,E表示图中边的集合,n=|V|m=|E|

V 中的全部 n 个顶点和 En1 条边构成的无向连通子图被称为 G 的一棵生成树,其中边的权值之和最小的生成树被称为无向图 G 的最小生成树。

然后我们看Kruskal的算法思想

1.将所有边按照权重从小到大排序,时间复杂度为O(mlogm)

2.枚举每条边a,b的权重c,如果a,b不连通的话,我们就把这一条边添加到集合当中。并查集实现合并、查询,时间复杂度O(m)

时间复杂度是很快的,所以在稀疏图当中,用Kruskal就可以了。

#include <iostream> #include <cstring> #include <algorithm> using namespace std; const int N = 200010; int n,m; int p[N];//并查集的数组 struct Edge{ int a,b,w; bool operator < (const Edge &W) const//重载运算符,用于后面排序 { return w < W.w; } }edge[N]; int find(int x) // 并查集 { if (p[x] != x) p[x] = find(p[x]); return p[x]; } int main() { scanf("%d%d", &n, &m); for (int i = 0; i < m; i ++ ) { int a,b,w; scanf("%d%d%d", &a, &b, &w); edge[i] = {a,b,w}; } sort(edge, edge + m); for (int i = 1; i <= n; i ++ ) p[i] = i; int res = 0;// 最小生成树里的所有权重之和 int cnt = 0;//当前加了多少条边 for (int i = 0; i < m; i ++ ) { int a = edge[i].a, b = edge[i].b, w = edge[i].w; a = find(a), b = find(b);//并查集查找根节点 if(a != b) { p[a] = b;//合并 res += w; cnt ++ ; } } if(cnt < n - 1) puts("impossible"); else printf("%d",res); return 0; }

喜欢的话请点开视频链接订阅我的频道


__EOF__

本文作者ljfyyds
本文链接https://www.cnblogs.com/ljfyyds/p/16490086.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   ljfyyds  阅读(57)  评论(1编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· AI 智能体引爆开源社区「GitHub 热点速览」
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具
点击右上角即可分享
微信分享提示