最小生成树-普利姆(Prim)算法

最小生成树

概念:将给出的所有点连接起来(即从一个点可到任意一个点),且连接路径之和最小的图叫最小生成树。最小生成树属于一种树形结构(树形结构是一种特殊的图),或者说是直链型结构,因为当n个点相连,且路径和最短,那么将它们相连的路一定是n-1条。

可以利用参考一个问题理解最小生成树,有n个村庄,每个村庄之间距离不同,要求村庄之间修路,每一个村庄必须与任意一个村庄联通,如何修路最省钱(修的最短)

普利姆算法介绍

利姆(Prim)算法求最小生成树,也就是在包含n个顶点的连通图中,找出只有(n-1)条边包含所有n个顶点的连通子图,也就是所谓的极小连通子图

具体过程如下:

(1)设G=(V,E)是连通网,T=(U,D)是最小生成树,V,U是顶点集合,E,D是边的集合

(2)若从顶点u开始构造最小生成树,则从集合V中取出顶点u放入集合U中,标记顶点v的visited[u]=1

(3)若集合U中顶点ui与集合V-U中的顶点vj之间存在边,则寻找这些边中权值最小的边,但不能构成回路,将顶点vj加入集合U中,将边(ui,vj)加入集合D中,标记visited[vj]=1

(4)重复步骤②,直到U与V相等,即所有顶点都被标记为访问过,此时D中有n-1条边

代码实现

不同的题目有不同的细节实现方式,因此本代码仅供参考

#include <stdio.h>
#include <stdlib.h>
#define n 20
#define MaxNum 10000 /*定义一个最大整数*/ /*定义邻接矩阵类型*/
typedef int adjmatrix[n + 1][n + 1];
typedef struct {
int fromvex, tovex; //生成树的起点和终点
int weight; //边的权重
} Edge;
typedef Edge *EdgeNode; //定义生成树的别名
int arcnum; /*边的个数*/ /*建立图的邻接矩阵*/
void CreatMatrix(adjmatrix GA) {
int i, j, k, e;
printf("=============================\n");
printf("图中有%d个顶点\n", n);
for(i=1; i<=n; i++) {
for(j=1; j<=n; j++) {
if(i==j) {
GA[i][j]=0; /*对角线的值置为0*/
} else {
GA[i][j]=MaxNum; /*其他位置的值置初始化为一个最大整数*/
}
}
}
printf("请输入边的个数:\n");
scanf("%d", &arcnum);
printf("请输入边的信息,依照起点,终点,权值的形式输入:\n");
for(k=1; k<=arcnum; k++) {
scanf("%d,%d,%d",&i,&j,&e); /*读入边的信息*/
GA[i][j]=e;
GA[j][i]=e;
}
} /*初始化图的边集数组*/
void InitEdge(EdgeNode GE,int m) {
int i;
for(i=1; i<=m; i++) {
GE[i].weight=0;
}
} /*依据图的邻接矩阵生成图的边集数组*/
void GetEdgeSet(adjmatrix GA,EdgeNode GE) {
int i, j, k = 1;
for(i=1; i<=n; i++) {
for(j=i+1; j<=n; j++) {
if(GA[i][j] !=0 && GA[i][j] != MaxNum) {
GE[k].fromvex = i;
GE[k].tovex = j;
GE[k].weight = GA[i][j];
k++;
}
}
}
} /*按升序排列图的边集数组*/
void SortEdge(EdgeNode GE,int m) {
int i,j,k;
Edge temp;
for(i=1; i<m; i++) {
k=i;
for(j=i+1; j<=m; j++) {
if(GE[k].weight > GE[j].weight) {
k=j;
}
}
if(k!=i) {
temp = GE[i];
GE[i]=GE[k];
GE[k]=temp;
}
}
} /*利用普里姆算法从初始点v出发求邻接矩阵表示的图的最小生成树*/
void Prim(adjmatrix GA,EdgeNode T) {
int i,j,k,min,u,m,w;
Edge temp;
/*给T赋初值。相应为v1依次到其余各顶点的边*/
k=1;
for(i=1; i<=n; i++) {
if(i!=1) {
T[k].fromvex=1;
T[k].tovex=i;
T[k].weight=GA[1][i];
k++;
}
}
/*进行n-1次循环,每次求出最小生成树中的第k条边*/
for(k=1; k<n; k++) {
min=MaxNum;
m=k;
for(j=k; j<n; j++) {
if(T[j].weight<min) {
min=T[j].weight;
m=j;
}
}
/*把最短边对调到k-1下标位置*/ 可用swap替换
temp=T[k];
T[k]=T[m];
T[m]=temp;
/*把新增加最小生成树T中的顶点序号赋给j*/
j=T[k].tovex;
/*改动有关边,使T中到T外的每个顶点保持一条到眼下为止最短的边*/
for(i=k+1; i<n; i++) {
u=T[i].tovex;
w=GA[j][u];
if(w<T[i].weight) {
T[i].weight=w;
T[i].fromvex=j;
}
}
}
} /*输出边集数组的每条边*/
void OutEdge(EdgeNode GE,int e) {
int i;
printf("依照起点,终点。权值的形式输出的最小生成树为:\n");
for(i=1; i<=e; i++) {
printf("%d,%d,%d\n",GE[i].fromvex,GE[i].tovex,GE[i].weight);
}
printf("=============================\n");
} int main() {
adjmatrix GA;
Edge GE[n*(n-1)/2], T[n];
CreatMatrix(GA);
InitEdge(GE,arcnum);
GetEdgeSet(GA,GE);
SortEdge(GE,arcnum);
Prim(GA,T);
printf("\n");
OutEdge(T,n-1);
return 0;
}

最小生成树-普利姆(Prim)算法的更多相关文章

  1. 图论---最小生成树----普利姆(Prim)算法

    普利姆(Prim)算法 1. 最小生成树(又名:最小权重生成树) 概念:将给出的所有点连接起来(即从一个点可到任意一个点),且连接路径之和最小的图叫最小生成树.最小生成树属于一种树形结构(树形结构是一 ...

  2. 图解最小生成树 - 普里姆(Prim)算法

    我们在图的定义中说过,带有权值的图就是网结构.一个连通图的生成树是一个极小的连通子图,它含有图中全部的顶点,但只有足以构成一棵树的n-1条边.所谓的最小成本,就是n个顶点,用n-1条边把一个连通图连接 ...

  3. 普里姆Prim算法介绍

    普里姆(Prim)算法,和克鲁斯卡尔算法一样,是用来求加权连通图的最小生成树的算法. 基本思想 对于图G而言,V是所有顶点的集合:现在,设置两个新的集合U和T,其中U用于存放G的最小生成树中的顶点,T ...

  4. 最小生成树-普利姆算法lazy实现

    算法描述 lazy普利姆算法的步骤: 1.从源点s出发,遍历它的邻接表s.Adj,将所有邻接的边(crossing edges)加入优先队列Q: 2.从Q出队最轻边,将此边加入MST. 3.考察此边的 ...

  5. JS实现最小生成树之普里姆(Prim)算法

    最小生成树: 我们把构造连通网的最小代价生成树称为最小生成树.经典的算法有两种,普利姆算法和克鲁斯卡尔算法. 普里姆算法打印最小生成树: 先选择一个点,把该顶点的边加入数组,再按照权值最小的原则选边, ...

  6. 最小生成树-普利姆算法eager实现

    算法描述 在普利姆算法的lazy实现中,参考:普利姆算法的lazy实现 我们现在来考虑这样一个问题: 我们将所有的边都加入了优先队列,但事实上,我们真的需要所有的边吗? 我们再回到普利姆算法的lazy ...

  7. POJ-2421-Constructing Roads(最小生成树 普利姆)

    Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 26694   Accepted: 11720 Description The ...

  8. 最小生成树——Prim(普利姆)算法

    [0]README 0.1) 本文总结于 数据结构与算法分析, 源代码均为原创, 旨在 理解Prim算法的idea 并用 源代码加以实现: 0.2)最小生成树的基础知识,参见 http://blog. ...

  9. 图的普里姆(Prim)算法求最小生成树

    关于图的最小生成树算法------普里姆算法 首先我们先初始化一张图: 设置两个数据结构来分别代表我们需要存储的数据: lowcost[i]:表示以i为终点的边的最小权值,当lowcost[i]=0说 ...

随机推荐

  1. Lock(锁)

    Lock(锁) 从JDK 5.0开始,Java提供了更加强大的线程同步机制----通过显示定义同步锁对象来实现同步.同步锁使用Lock对象充当. java.util.concurrent.locks. ...

  2. 小知识get:利用单臂路由实现不同vlan间路由

    一.单臂路由概述 1.1.单臂路由实现不同vlan间通信 链路类型 交换机连接主机的端口为access链路 交换机连接路由器的端口为Trunk链路 子接口 路由器的物理接口可以被划分成多个逻辑接口 每 ...

  3. 披着羊皮的Neo-reGeorg

    混迹 Web 安全行业许久,查杀网站后门已是家常便饭.时间久了,养"马"场也见的多了,Neo-reGeorg 算得上是同类中战斗力超群的"野马"了,也深受黑客和 ...

  4. 【Java】@Scheduled常用的注解的使用

    @Scheduled注解的使用 cron cron这个参数必须要接受一个cron表达式 cron表达式是个啥呢,Cron表达式是一个具有时间含义的字符串,字符串以5个空格隔开,分为6个域,格式为 X ...

  5. linux联网、远程

    使用VMware虚拟机创建linux系统CentOS 7,连接网络以及远程Moba工具. 一.首先安装好VMware虚拟机和CentOS系统,网上很多教程,不在赘述. 二.打开VMware进行配置 1 ...

  6. SQL injection : UNION attacks

    当应用程序易受SQL注入攻击并且查询结果在应用程序的响应中返回时,可以使用UNION关键字从数据库中的其他表检索数据.这将导致SQL注入联合攻击. UNION关键字允许您执行一个或多个附加的SELEC ...

  7. Sqli-Labs less23-24

    less-23 23关和第1关很像,但是观察代码发现他对--+和#都进行了转义,不能再用这种方式注释 可以用新的注释符:;%00或者and和or语句进行闭合 语句:http://192.168.5.1 ...

  8. 微信小程序开发(二)——使用WeUI组件库

    一.前言 因为小程序的api描述都比较简单,并没有wxml及wxss的描述,一定会想小程序有没有一个UI库,类似于前端中的Bootstrap,MD,Semantic UI这样的框架UI库.有的,它就是 ...

  9. luogu P2473 奖励关

    奖励关 看到数据范围,想到状压,那问题就是如何设计方程 设\(dp[i][j]\)表示在第\(i\)轮的时候,状态为\(j\)时的最优策略所拿的分值,\(j\)的二进制下为1的位置,表示选了这个宝物, ...

  10. uwp 语音指令

    Xml code -------------------------------- <Page x:Class="MyApp.MainPage" xmlns="ht ...