博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
prim算法基础详解(无向赋权图的最小生成树MST)
阅读量:5264 次
发布时间:2019-06-14

本文共 2220 字,大约阅读时间需要 7 分钟。

带权图分为有向和无向,无向图的最短路径又叫做最小生成树,有prime算法和kruskal算法

生成树的概念:联通图G的一个子图如果是一棵包含G的所有顶点的树,则该子图称为G的生成树 生成树是联通图的极小连通子图。

所谓极小是指:若在树中任意增加一条边,则将出现一个回路;若去掉一条边,将会使之变成非连通图。生成树各边的权值总和称为生成树的权。

权最小的生成树称为最小生成树,常用的算法有prime算法和kruskal算法。这里仅介绍prime算法..

算法描述如下:

1.将所有的结点分成两个集合。一部分是在最小生成树中的点(记为集合A),另一部分是不在最小生成树中的点(即待加入的点,记为集合B)。

2.开始的时候取任意一个点v作为顶点加入最小生成树中(A),然后遍历集合B,选取一个点vj使得(v,vj)的权值最小,然后将vj加入A集合,B集合中删去vj(删去操作可以用一个intree[i]数组来进行操作)

3.重复2步骤直到所有点遍历完毕。

注意:这里说的重复步骤2是指每次找的与顶点v的边权值最小的结点!

结合例子来看一下。(如下图)

选择1为初始结点,intree[1]标记为1.

遍历剩下的6个结点,找到(1,vj)中weight最小的那一个,显然是3,让3加入集合A,即intree[3]标记为1 

然后注意此时集合A中有了两个元素(结点1和结点3)开始的时候我认为是从3开始遍历找3与其他点的最小权值,但是再次注意我们每次只找与顶点(这里就1结点)边权值最小的点。

3结点入队后,1就可以与5结点间接相连了,所以每次在A中加入一个结点,都要更新顶结点与其他结点的关联与否以及权值。

这一点非常重要是算法的重要步骤。

正如此时(1,5) = 8  (1,4) = 5 (1,2) = 6 ,显然下一次应该加入A集合的是点4,所以:

接下来就是:

附上代码及测试样例。

#include 
#include
#define maxn 10#define INF 100000int node;int G[maxn + 1][maxn + 1];/*构建的图,必须是一个无向连通赋权图,G[i][j]存取权值*/ int intree[maxn];/*结点i在最小生成树中*/ int minweight[maxn];/*到i点的最小权重*/ int sumweight;void initialize(){ memset(intree,0,sizeof(intree)); memset(minweight,0,sizeof(minweight)); for(int i = 0 ; i <= maxn ; i++) for(int j = 0 ; j <= maxn ; j++) G[i][j] = INF; sumweight = 0;}void prime(int n){ int node,Minweight; for(int i = 1 ; i <= n ; i++) minweight[i] = G[1][i]; /*先把1结点放进最小生成树,那么要知道1到其余结点的最小权重*/ intree[1] = 1;/*1点进入集合A,最小生成树集*/ for(int i = 2 ; i <= n ; i++) /*一共n个点,已经把1加入最小生成树,那么还剩下n-1个点*/ { Minweight = INF; for(int j = 1 ; j <= n ; j++) { if(minweight[j] < Minweight && !intree[j]) { Minweight = minweight[j]; node = j; } } printf("选择的结点标号为:%d\n",node); intree[node] = 1; sumweight += Minweight; /*每次在A中加入新的点,更新顶结点到各节点的权重*/ for(int j = 1 ; j <= n ; j++) if(!intree[j] && minweight[j] > G[node][j]) /*更新B集合*/ minweight[j] = G[node][j]; }}int main(){ int Node,Edge; int vertex1,vertex2,weight; initialize(); scanf("%d%d",&Node,&Edge); for(int i = 1 ; i <= Edge ; i++) { scanf("%d%d%d",&vertex1,&vertex2,&weight); G[vertex1][vertex2] = weight; G[vertex2][vertex1] = weight; } prime(Node); printf("%d\n",sumweight); return 0;}/*7 91 2 61 3 21 4 52 5 22 7 43 5 84 6 74 7 55 6 10答案是25 */

转载于:https://www.cnblogs.com/sixdaycoder/p/4348384.html

你可能感兴趣的文章
简单的数据库操作
查看>>
帧的最小长度 CSMA/CD
查看>>
树状数组及其他特别简单的扩展
查看>>
普通求素数和线性筛素数
查看>>
PHP截取中英文混合字符
查看>>
【洛谷P1816 忠诚】线段树
查看>>
电子眼抓拍大解密
查看>>
tomcat7的数据库连接池tomcatjdbc的25个优势
查看>>
Html 小插件5 百度搜索代码2
查看>>
java.io.IOException: read failed, socket might closed or timeout, read ret: -1
查看>>
java 常用命令
查看>>
卷积中的参数
查看>>
51nod1076 (边双连通)
查看>>
ViewPager的onPageChangeListener里面的一些方法参数:
查看>>
Linux pipe函数
查看>>
java equals 小记
查看>>
2019春 软件工程实践 助教总结
查看>>
Zerver是一个C#开发的Nginx+PHP+Mysql+memcached+redis绿色集成开发环境
查看>>
多线程实现资源共享的问题学习与总结
查看>>
java实现哈弗曼树
查看>>