最小生成树(Prim与Kruskal)

12 篇文章 0 订阅
6 篇文章 0 订阅

Prim:Prim实际上与最短路的Dij,Bellman-ford类似,都是运用蓝白点的思维.开一个bool数组白点(0)表示未进入最小生成树的点.蓝点(1)表示已进入最小生成树的点.

Prim算法与Dij一样,不能够处理负边权的情况(思维与贪心类似).

先初始化 :min[i]=无穷大,表示以1为起点的最小生成树蓝点(i)与白点连接的最小边权.min[1]=0,表示以1为起点,边权为0,之后ans=0.

计算:for(i=1;i<=n;i++)

寻找min[x]最小的x,把x标记为白点,ans+=min[x];最后再次寻找与白点x相连的所有蓝点,一次结束.

两层循环,第一层枚举n个点,第二层查找蓝点与白点,时间复杂度O(n^2).

Kruskal:Kruscal与Prim思维不太相同,需要用到并查集+链表。首先需要把相互连通的一些点放入同一连通块中.

先初始化:father[i]=i;(可以用路径压缩与启发式合并,这样并查集时间复杂度可以变成O(n).

再写链表,我比较愿意用结构体(也可以不用).

head[i]表示i前面的点是谁,edge[i].to表示到达谁,edge[i].next表示下一个点是谁,edge[i].value表示边权是多少.数组一定要开边的2倍,因为存的是双向边.

把idx先置成0.

void addedge(int a,int b,int c)

{

edge[++idx].next=head[a];

head[a]=idx;

edge[idx].to=b;

edge[idx].value=c;

}

之后调用两遍函数就存进来了.

并查集这里就不详细说了,等总结到并查集时再说.

ans=0;

之后所有边的权值从小到大排序(sort)即edge[i].value.

这里就是要用并查集的时刻,判断这条边是否在并查集中,如果在,就不用加入最小生成,如果不在,就加入.

ans+=edge[i].value;

每加入一条边,层数+1,如果层数=n-1,表示最小生成树已生成,结束.

一共E条边,sort排序O(ElogE),并查集O(n),总:ElogE.

总结:看情况选择Prim与Kruskal两种算法,在稀疏图中(E接近n时),Kruskal可以达到O(nlogn),但是在稠密图中(E接近n^2时),Kruskal为O(n^2logn),不如Prim.这种时间复杂度如果非要用Kruskal做的话可以直接用邻接矩阵.

这是博主第一篇文章,有问题可以尽情评论,感谢大家的支持.

 

 

  • 4
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值