1. 图的最小生成树
生成树的定义:如果连通图G的一个子图是一棵包含G的所有顶点的树,则该子图称为G的生成树。
生成树是连通图的包含图中的所有顶点的极小连通子图。它并不唯一,从不同的顶点出发进行遍历,可以得到不同的生成树。
其中,权值最小的树就是最小生成树。
关于最小生成树最经典的应用模型就是城市通信线路网最小造价的问题:网络G表示n个城市之间的通信线路(其中顶点表示城市,边表示两个城市之间的通信线路,边上的权值表示线路的长度或造价),通过求该网络的最小生成树找到求解通信线路总造价最小的最佳方案。
求图的最小生成树主要有两种经典算法:
- 普里姆(Prim)算法
时间复杂度为O(n2),适合于求边稠密的最小生成树。 - 克鲁斯卡尔(Kruskal)算法
2. 普里姆(Prim)算法
2.1 算法思想
取图中任意一个顶点V作为生成树的根,之后若要往生成树上添加顶点W,则在顶点V和W之间必定存在一条边。并且该边的权值在所有连通顶点V和W之间的边中取值最小。
2.2 算法实现
- 输入:一个加权连通图,其中顶点集合为V,边集合为E;
- 初始化:Vnew = {x},其中x为集合V中的任一节点(起始点),Enew = {}为空;
重复下列操作,直到Vnew = V:
a.在集合E中选取权值最小的边<u, v>
,其中u为集合Vnew中的元素,而v不在Vnew集合当中,并且v∈V(如果存在有多条满足前述条件即具有相同权值的边,则可任意选取其中之一);
b.将v加入集合Vnew中,将<u, v>
边加入集合Enew中;输出:使用集合Vnew和Enew来描述所得到的最小生成树。
完整实现的示意图如下:
代码实现为:
int edge[1005][1005];//用邻接矩阵表示的图
int book[1005];//已确定的节点集合
int dis[1005];//最短路径
int num=0;//节点的总个数
int prim(int s) {