首页 > 编程知识 正文

kruskal算法求最小生成树,prim算法步骤

时间:2023-05-06 01:28:51 阅读:174232 作者:747

棱镜算法(Prim算法)的概要http://www.Sina.com),用图论中的算法可以在加权连通图中检索http://www.Sina.com。 也就是说普里姆算法(Prim算法)(英语: vertex ) graphtheory ) ) ),其所有边的权重之和也是最小的。 该算法于1930年由捷克数学家ggdgtx (英文: Vojtch Jarnk )发现; 1957年被美国计算机科学家怡园的帽子(Robert C. Prim )独立发现。1959年,紧张的香菇再次发现了该算法。 因此,在某些情况下,prime算法也被称为DJP算法、al智能树叶算法或prime智能树叶算法。

算法说明输入:设顶点集合为v,边集合为e的加权连通图; 初始化: V n e w V_{new} Vnew ={x}其中x是集合v中的任意节点(起点),E n e w E_{new} Enew ={},为空; 重复以下操作,直到V n e w V_{new} Vnew=V。

a .在集合e中选择权重最小的边u,v。 其中,u是集合V n e w V_{new} Vnew中的要素,v不在V n e w V_{new} Vnew的集合中,且vV (满足上述条件,即存在多个具有相同权重的边时,选择任意一个

将b.v放入集合V n e w V_{new} Vnew,将u,v边放入集合E n e w E_{new} Enew; 输出:使用集合V n e

w V_{new} Vnew​和 E n e w E_{new} Enew​来描述所得到的最小生成树。 图示

简略证明

反证法:假设prim生成的不是最小生成树

设prim生成的树为G0假设存在 G m i n G_{min} Gmin​使得cost( G m i n G_{min} Gmin​)< cost( G 0 G_{0} G0​) 则在 G m i n G_{min} Gmin​中存在< u,v>不属于 G 0 G_{0} G0​将< u,v>加入 G 0 G_{0} G0​中可得一个环,且< u,v>不是该环的最长边(这是因为< u,v>∈ G m i n G_{min} Gmin​)这与prim每次生成最短边矛盾故假设不成立,命题得证 基本操作函数

prim(n):建立最小生成树,并输出其权值和

代码模板(含详细注释)

这里用 http://poj.org/problem?id=1258 作为模板题

#include <stdio.h>#include <stdlib.h>#include <string.h>#define N 110 //最多顶点数#define MAX 0x3f3f3f3f //模拟无穷大int map[N][N]; //存储各顶点间的权值int flag[N]; //标记是否已纳入树int dis[N]; //已纳入点和其余各点的最小权值int prim(int n) //qrdyd函数{ int i, j; int now; //记录新纳入的点 int min; //记录新纳入的点到其余已纳入的点的最小权值 int sum = 0; //最小生成树权值和 memset(dis, MAX, sizeof(dis)); //初始化dis数组为无穷大 memset(flag, 0, sizeof(flag)); //初始化flag数组,0表示此点未被纳入 /*这里随机选取了1号点为初始时被纳入的顶点*/ for(i = 1; i <= n; i++) dis[i] = map[1][i]; //与1号点与其他点的权值存入dis数组 dis[1] = 0; //一号点到其本身的权值为0 flag[1] = 1; //标记为已纳入 for(i = 1; i < n; i++){ //除去初始时随机纳入的点还有n-1个点应被纳入 now = min = MAX; //初始为无穷大表示两点间无通路 for(j = 1; j <= n; j++){ //遍历 if(flag[j] == 0){ if(dis[j] < min){ //寻找与已纳入各点权值最小的点 now = j; min = dis[j]; } } } if(now == MAX) //若now等于max,则证明所有与初始时纳入的点连通的点已全被纳入 break; sum += min; //将找到的点纳入并标记 flag[now] = 1; for(j = 1; j <= n; j++){ /* 遍历比较之前纳入点到未纳入点的权值的最小值 与刚纳入点到未纳入点的权值 并用dis[j]存储新的最小值 */ if(flag[j] == 0) if(dis[j] > map[now][j]) dis[j] = map[now][j]; } } if(i == n) //若i等于n则证明已经建立最小生成树 return sum; else return -1;}int main(void){ int i, j, k; int n; //顶点数 while(scanf("%d", &n) != EOF){ for(i = 1; i <= n; i++) for(j = 1; j <= n; j++) scanf("%d", &map[i][j]); //输入i和j之间的距离 if((k = prim(n)) != -1) //调用prim函数 printf("%dn", k); else printf("烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫n"); } return 0;}

模板题样例图解

运行示例

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。