最小生成树

本文详细介绍了两种经典的最小生成树算法——Prim算法和Kruskal算法。Prim算法使用蓝白点思想,通过不断将最接近当前生成树的顶点加入来构建最小生成树,时间复杂度为O(n²)。Kruskal算法则采用加边法,通过排序后的边依次尝试加入生成树中,避免形成环路,时间复杂度为O(eloge)。

最小生成树

Prim

时间复杂度O(n2)

蓝白点思想,蓝点代表为纳入最小生成树的点,白点代表已纳入的点。

初始化所有点到最小生成树的距离;(极大值)

选择一个点作为树的根节点;(没有要求的话,一般选择第一个点)

枚举该点出发的所有边,进行松弛操作,并将该点标为白色;

从蓝点中选取离最小生成树最近的点进行松弛操作,并加入最小生成树;

如此循环,直到所有点都加入最小生成树;

例题:【模板】最小生成树

算法结束。

复制代码
#include<cstdio>
#include<iostream>
using namespace std;
const int inf=100000000; int n,ans,p,b; int a[110],map[110][110]; bool v[110]; int main(){ scanf("%d",&n); for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) scanf("%d",&map[i][j]); for(int i=1;i<=n;i++) a[i]=map[1][i]; v[1]=1; for(int i=1;i<n;i++){ p=inf; for(int i=1;i<=n;i++) if(!v[i]&&a[i]<p){p=a[i];b=i;} ans+=a[b];v[b]=1; for(int i=1;i<=n;i++) a[i]=min(a[i],map[b][i]); } printf("%d\n",ans); return 0; }
复制代码

 

Kruskal

时间复杂度O(eloge)

加边法。

首先,对所有边进行排序,时间复杂度O(eloge);

从小到大枚举边,如果边的两端已经处于同一个集合,加入该边,否则不加入。

复制代码
 1 #include<cstdio>
 2 #include<algorithm>
 3 using namespace std;  4 int n,m,a,b,ans;  5 int fa[5010];  6 struct nate{  7 int q,z,bq;  8 }edge[200010];  9 int comp(const nate&x,const nate&y ){return x.bq<y.bq;} 10 int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);} 11 int main(){ 12 scanf("%d%d",&n,&m); 13 for(int i=1;i<=m;i++) scanf("%d%d%d",&edge[i].q,&edge[i].z,&edge[i].bq); 14 sort(edge+1,edge+m+1,comp); 15 for(int i=1;i<=n;i++) fa[i]=i; 16 for(int i=1;i<=m;i++){ 17 a=find(edge[i].q);b=find(edge[i].z); 18 if(a!=b){ 19 ans+=edge[i].bq; 20 fa[b]=a; 21  } 22  } 23 printf("%d\n",ans); 24 return 0; 25 }
复制代码

 

从时间复杂度来看,两种算法各有优劣,不过在OI中,一般的图都是点多边少,所以Kruskal可能更常用一些;

转载于:https://www.cnblogs.com/J-william/p/6821439.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值