最小生成树——Kruskal
题目描述
如题,给出一个无向图,求出最小生成树,如果该图不连通,则输出 orz。
输入格式
第一行包含两个整数 N,M,表示该图共有 N 个结点和 M 条无向边。 接下来 M 行每行包含三个整数 X_i,Y_i,Z_i,表示有一条长度为 Z_i 的无向边连接结点 X_i,Y_i。
输出格式
如果该图连通,则输出一个整数表示最小生成树的各边的长度之和。如果该图不连通则输出 orz。
样例输入
6 9
2 4 11
3 5 13
4 6 3
5 6 4
2 3 6
4 5 7
1 2 1
3 4 9
1 3 2
样例输出
19
数据规模:
对于 20% 的数据,N≤5,M≤20。 对于 40% 的数据,N≤50,M≤2500。 对于 70% 的数据,N≤500, M≤10^4 。 对于 100% 的数据:1≤N≤5000,1≤M≤2×10^5 。
最小生成树的定义
对于一张图,用最少的边让图连通(任意两点之间可以互相到达),其实就是将多余的边去掉。很显然,要想让有n个定点的图连通,那么至少需要n-1条边,如果一个连通无向图不包含回路(环),那么就是一棵树,最小生成树就是求用最少的费用连通一个无向图,也就是求n-1条边连通一个无向图的总长度最短。
Kruskal算法(贪心)
适用于稀疏图(M远远大于N)
既然要求是让边的总长度最短,我们自然可以想到首先选择最短的边,然后选择次短的边……直到选择了n-1条边为止。这就需要先对所有的边按照权值进行从小到大排序,然后从最小的开始选,依次选择每一条边,直到选择了n-1条边让整个图连通为止。
对边排序如下:
1 2 1
1 3 2
4 6 3
5 6 4
2 3 6
4 5 7
3 4 9
2 4 11
3 5 13
选择过程如下:
1)
2)
3)
4)
5)
到目前为止都很完美,直到选用 2 3 6 这条边时,我们发现此时 2 号顶点和 3 号顶点已经连通了,不再需要 2 3 6 这条边(因为我们对边排序了,好好想想吧~~)。如果加上这条边就会形成回路,那就不是树了,因此需要跳过这条边。
接下来是 4 5 7 这条边,同理这条边我们也不能选用。
最终选用 3 4 9 这条边后,我们已经选用了n-1条边,图已经连通,算法结束,如下:
难点
回顾刚才的算法,比较难于实现的是:判断两个顶点是否已连通。这一点我们可以使用深度优先搜索或者广度优先搜索来解决,但这样效率很低。我们有更好的选择,那就是并查集。将所有的顶点放入一个并查集中,判断两个顶点是否连通,只需判断两个顶点是否在同一个集合(即是否有共同的祖先)即可。这样时间复杂度仅为O(logN)。
算法实现步骤
1、对边排序(sort); 2、初始化(i的父亲是自己(i)); 3、如果两点尚未连通,cnt+1,合并两点(并查集); 4、return 0;
时间复杂度 对边进行快速排序是O(MlogM),在m条边中找出n-1条边是O(MlogN),所以Kruskal算法的时间复杂度为O(MlogM+MlogN)。通常M要比N大很多,因此时间复杂度为O(MlogM)。 —————————AC代码
#include<bits/stdc++.h>
using namespace std;
int n,m,fa[1000001],countt,sum;
struct edge{
int u,v,w;
}e[1000001];
bool comp(edge a,edge b){
return a.w<b.w;
}
int get(int x){
return fa[x]==x?x:fa[x] = get(fa[x]);
}
bool merge(int x, int y){//判断是否<尚未>连通
x = get(x);y = get(y);
if(x==y)return false;
fa[y] = x;
return true;
}
void Kruskal(){
for(int i=1;i<=m;i++){
if(merge(e[i].u,e[i].v))countt++,sum+=e[i].w;
if(countt==n-1)return;
}
}
int main(){
cin>>n>>m;
for(int i=1;i<=m;i++)cin>>e[i].u>>e[i].v>>e[i].w;
sort(e+1,e+m+1,comp);
for(int i=1;i<=n;i++)fa[i]=i;
Kruskal();
cout<<sum;
//if(countt==n-1)cout<<sum;//判断图是否连通
//else cout<<"orz";
//防抄袭————QAQ
return 0;
}
————————QAQ
本文来自博客园,作者:蒟蒻orz,转载请注明原文链接:https://www.cnblogs.com/orzz/p/18122215
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话