图论——最小生成树

基本概念

在无向图中,连通且不含环的图称为树。

  1. 生成树的定义
      在一个v个点的无向连通图中,取其中v-1条边,并连接所有的顶点,所得到的子图称为原图的一棵生成树;
  2. 最小生成树
      在一个带权的无向连通图中,各边权和最小的一棵生成树即为原图的最小生成树;
  3. 最小边原则
      图中权值最小的边(如果唯一的话)一定在最小生成树上;
  4. 唯一性原则
      对于一个图G,如果图中的边权值都不相同,则图的最小生成树是惟一的,反之不然;

prim算法

思想

prim算法是一种贪心算法她最初将无向联通图G中所有顶点V分成两个顶点集合VA和VB。在计算过程中VA中的点为已经选好的连接入生成树的点,否则属于VB。最开始的时候VA只包含任意选取的图G中的一个点u,其余的点属于VB,每次添加一个VB中的点(集合VB到集合VA中距离最小的那个点)到集合VA。直到V个顶点全部属于VA,算法结束。显然出发点不同,最小生成树的形态就不同,但边权和的最小值是唯一的。

算法步骤

选定图中的任意一个顶点V0,从V0开始生成最小数:

  1. 初始化dis[V0]=0,其他点的距离值dis[i]为极大值。其中dis[i]表示集合VB中的点到集合VA中的点的距离值。
  2. 经过N次以下步骤,最后得到最小生成树:
      ①. 选择一个未被标记的点k,并且dis[k]的值是最小的;
      ②.标记点k进入集合VA;
      ③.以k为中心点,修改未标记点j,即VB中的点到VA的距离值;
  3. 得到最小生成树。

伪代码
for(int i=1;i<=n;i++) dis[i]=inf;
dis[1]=0;
for(int i=1;i<=n;i++)
 for(int j=1;j<=n;j++)
  找dis[j]最小&&vis[j]==0的点j,
  vis[j]=1;
  更新j->k的dis[k];

时间复杂度

最小边、权的数据结构 时间复杂度(总计)
邻接矩阵、搜索 O(V^2)
二叉堆、邻接表 O((V + E) log(V)) = O(E log(V))
斐波那契堆、邻接表 O(E + V log(V))

通过邻接矩阵图表示的简易实现中,找到所有最小权边共需O(V)的运行时间。使用简单的二叉堆与邻接表来表示的话,普里姆算法的运行时间则可缩减为O(ElogV),其中E为连通图的边数,V为顶点数。如果使用较为复杂的斐波那契堆,则可将运行时间进一步缩短为O(E+VlogV),这在连通图足够密集时(当E满足Ω(VlogV)条件时),可较显著地提高运行速度。

图例描述

图例 说明 不可选 可选 已选(VA)
在这里插入图片描述 此为原始的加权连通图。每条边一侧的数字代表其权值。 - - -
在这里插入图片描述 顶点D被任意选为起始点。顶点A、B、E和F通过单条边与D相连。A是距离D最近的顶点,因此将A及对应边AD以高亮表示。 C, G A, B, E, F D
在这里插入图片描述 下一个顶点为距离D或A最近的顶点。B距D为9,距A为7,E为15,F为6。因此,F距D或A最近,因此将顶点F与相应边DF以高亮表示。 C, G B, E, F A, D
在这里插入图片描述 算法继续重复上面的步骤。距离A为7的顶点B被高亮表示。 C B, E, G A, D, F
在这里插入图片描述 在当前情况下,可以在C、E与G间进行选择。C距B为8,E距B为7,G距F为11。点E最近,因此将顶点E与相应边BE高亮表示。 C, E, G A, D, F, B
在这里插入图片描述 这里,可供选择的顶点只有C和G。C距E为5,G距E为9,故选取C,并与边EC一同高亮表示。 C, G A, D, F, B, E
在这里插入图片描述 顶点G是唯一剩下的顶点,它距F为11,距E为9,E最近,故高亮表示G及相应边EG。 G A, D, F, B, E, C
在这里插入图片描述 现在,所有顶点均已被选取,图中绿色部分即为连通图的最小生成树。在此例中,最小生成树的权值之和为39。 A, D, F, B, E, C, G

模板

#include<iostream>
using namespace std;
const int maxn=1<<31-1;
int map[505][505],vis[505],dis[505],n,m,ans;
//vis[i]标记顶点i是否在最小生成树中
//dis[i]表示点i与当前生成树中的点有连边的边长最小值 
void read()//建图 <
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值