最小生成树

所谓最小生成树,就是一个图的极小连通子图,它包含原图的所有顶点,并且所有边的权值之和尽可能的小。

首先看看第一个例子,有下面这样一个带权图:

它的最小生成树是什么样子呢?下图绿色加粗的边可以把所有顶点连接起来,又保证了边的权值之和最小:

去掉那些多余的边,该图的最小生成树如下:

下面我们再来看一个更加复杂的带权图:

同样道理,下图绿色加粗的边可以把所有顶点连接起来,又保证了边的权值之和最小:

去掉那些多余的边,该图的最小生成树如下:

图的极小连通子图不需要回路,而是一个树形结构,所以人们才把它叫做最小生成【树】。图的最小生成树也不是唯一的,同一个图可以有多个不同的最小生成树,但是他们的权值之和是一样的。

最小生成树的用处可多了,比如我们要在若干个城市之间铺设道路,而我们的预算又是有限的,那么我们就需要找出成本最低的方式铺路,最小生成树的作用就来了。

怎样铺设才能保证成本最低呢?

城市之间的交通网就像一个连通图,我们并不需要在每两个城市之间都直接进行连接,只需要一个最小生成树,保证所有的城市都有铁路可以触达即可。

通常生成最小生成树常用的算法有两种,一种是 Kruskal 算法,另一种是 Prim 算法。下面介绍下 Prim 算法

Prim算法是如何工作的呢?

这个算法是以图的顶点为基础,从一个初始顶点开始,寻找触达其他顶点权值最小的边,并把该顶点加入到已触达顶点的集合中。当全部顶点都加入到集合时,算法的工作就完成了。Prim算法的本质,是基于贪心算法

接下来说一说最小生成树的存储方式。我们最常见的树的存储方式,是链式存储,每一个节点包含若干孩子节点的指针,每一个孩子节点又包含更多孩子节点的指针:

这样的存储结构很清晰,但是也相对麻烦。为了便于操作,我们的最小生成树用一维数组来表达,数组下标所对应的元素,代表该顶点在最小生成树当中的父亲节点。(根节点没有父亲节点,所以元素值是-1)

下面让我们来看一看算法的详细过程:

1.选择初始顶点,加入到已触达顶点集合。

2.从已触达顶点出发,寻找到达新顶点的权值最小的边。显然从0到2的边权值最小,把顶点2加入到已触达顶点集合,Parents当中,下标2对应的父节点是0。

 

3.从已触达顶点出发,寻找到达新顶点的权值最小的边。显然从2到4的边权值最小,把顶点4加入到已触达顶点集合,Parents当中,下标4对应的父节点是2。

4.从已触达顶点出发,寻找到达新顶点的权值最小的边。显然从0到1的边权值最小,把顶点1加入到已触达顶点集合,Parents当中,下标1对应的父节点是0。

5.从已触达顶点出发,寻找到达新顶点的权值最小的边。显然从1到3的边权值最小,把顶点3加入到已触达顶点集合,Parents当中,下标3对应的父节点是1。

这样一来,所有顶点都加入到了已触达顶点集合,而最小生成树就存储在Parents数组当中。

Java:

import java.io.*;
import java.util.*; class Test
{
final static int INF = Integer.MAX_VALUE;
public static int[] prim(int[][]matrix){
List <Integer> reachedVertexList = new ArrayList<Integer>();
//选择顶点0为初始顶点,放入已触达顶点集合中
reachedVertexList.add(0);
//创建最小生成树数组,首元素设为-1
int[] parents = new int[matrix.length];
parents[0]=-1;
//边的权重
int weight;
     //源顶点下标
int fromIndex = 0;
     //目标顶点下标
int toIndex =0;
while(reachedVertexList.size() < matrix.length){
weight =INF;
       //在已触达的顶点中,寻找到达新顶点的最短边
for(Integer vertexIndex :reachedVertexList){
for(int i =0;i <matrix.length;i++){
if(!reachedVertexList.contains(i)){
if(matrix[vertexIndex][i]<weight){
fromIndex =vertexIndex;
toIndex =i;
weight =matrix[vertexIndex][i];
}
}
}
}
//确定了权值最小的目标顶点,放入已触达顶点集合
reachedVertexList.add(toIndex);        //放入最小生成树的数组
parents[toIndex]=fromIndex;
}
return parents;
} public static void main(String[]args){
int[][]matrix =new int[][]{
{0,4,3,INF,INF},
{4,0,8,7,INF},
{3,8,0,INF,1},
{INF,7,INF,0,9},
{INF,INF,1,9,0},
};
int[]parents =prim(matrix);
System.out.println(Arrays.toString(parents));
} }

运行结果:

[-1, 0, 0, 1, 2]

这段代码当中,图的存储方式是邻接矩阵,在main函数中作为测试用例的图和对应的邻接矩阵如下:

最小生成树,Prim算法实现的更多相关文章

  1. 数据结构代码整理(线性表,栈,队列,串,二叉树,图的建立和遍历stl,最小生成树prim算法)。。持续更新中。。。

    //归并排序递归方法实现 #include <iostream> #include <cstdio> using namespace std; #define maxn 100 ...

  2. 最小生成树Prim算法(邻接矩阵和邻接表)

    最小生成树,普利姆算法. 简述算法: 先初始化一棵只有一个顶点的树,以这一顶点开始,找到它的最小权值,将这条边上的令一个顶点添加到树中 再从这棵树中的所有顶点中找到一个最小权值(而且权值的另一顶点不属 ...

  3. 最小生成树—prim算法

    最小生成树prim算法实现 所谓生成树,就是n个点之间连成n-1条边的图形.而最小生成树,就是权值(两点间直线的值)之和的最小值. 首先,要用二维数组记录点和权值.如上图所示无向图: int map[ ...

  4. Highways POJ-1751 最小生成树 Prim算法

    Highways POJ-1751 最小生成树 Prim算法 题意 有一个N个城市M条路的无向图,给你N个城市的坐标,然后现在该无向图已经有M条边了,问你还需要添加总长为多少的边能使得该无向图连通.输 ...

  5. SWUST OJ 1075 求最小生成树(Prim算法)

    求最小生成树(Prim算法) 我对提示代码做了简要分析,提示代码大致写了以下几个内容 给了几个基础的工具,邻接表记录图的一个的结构体,记录Prim算法中最近的边的结构体,记录目标边的结构体(始末点,值 ...

  6. 图论算法(五)最小生成树Prim算法

    最小生成树\(Prim\)算法 我们通常求最小生成树有两种常见的算法--\(Prim\)和\(Kruskal\)算法,今天先总结最小生成树概念和比较简单的\(Prim\)算法 Part 1:最小生成树 ...

  7. 最小生成树,Prim算法与Kruskal算法,408方向,思路与实现分析

    最小生成树,Prim算法与Kruskal算法,408方向,思路与实现分析 最小生成树,老生常谈了,生活中也总会有各种各样的问题,在这里,我来带你一起分析一下这个算法的思路与实现的方式吧~~ 在考研中呢 ...

  8. 最小生成树——prim算法

    prim算法是选取任意一个顶点作为树的一个节点,然后贪心的选取离这棵树最近的点,直到连上所有的点并且不够成环,它的时间复杂度为o(v^2) #include<iostream>#inclu ...

  9. 最小生成树--Prim算法,基于优先队列的Prim算法,Kruskal算法,Boruvka算法,“等价类”UnionFind

    最小支撑树树--Prim算法,基于优先队列的Prim算法,Kruskal算法,Boruvka算法,“等价类”UnionFind 最小支撑树树 前几节中介绍的算法都是针对无权图的,本节将介绍带权图的最小 ...

  10. 求最小生成树(Prim算法)(1075)

    Description 求出给定无向带权图的最小生成树.图的定点为字符型,权值为不超过100的整形.在提示中已经给出了部分代码,你只需要完善Prim算法即可. Input 第一行为图的顶点个数n    ...

随机推荐

  1. poj 2187 Beauty Contest(平面最远点)

    Beauty Contest Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 24431   Accepted: 7459 D ...

  2. openprocess打不开 如何读取exe路径描述

    openprocess打不开 如何读取exe路径描述 openprocess打不开 如何读取exe路径描述 https://bbs.pediy.com/thread-210652.htm https: ...

  3. 定位公众号页面,跳转之后 vuejs 失效问题

    是第一个页面的. data () { }, 写成了这样,没写返回 {} 5555~. 网页中死活可以,微信中死活不行. data () { return {} },

  4. Java技术中如何使用keepalived实现双机热备

    Keepalived简介 Keepalived是Linux下一个轻量级别的高可用解决方案.高可用(High Avalilability,HA),其实两种不同的含义:广义来讲,是指整个系统的高可用行,狭 ...

  5. python开发之virtualenv与virtualenvwrapper

    在使用 Python 开发的过程中,工程一多,难免会碰到不同的工程依赖不同版本的库的问题: 亦或者是在开发过程中不想让物理环境里充斥各种各样的库,引发未来的依赖灾难. 此时,我们需要对于不同的工程使用 ...

  6. JavaScript 函数防抖

    <!DOCTYPE html><html lang="zh-cmn-Hans"> <head> <meta charset="u ...

  7. 对vue的研究

    beforeDestroy 类型:Function 详细: 实例销毁之前调用.在这一步,实例仍然完全可用. 该钩子在服务器端渲染期间不被调用. 参考:生命周期图示 destroyed 类型:Funct ...

  8. simulate 中的一些操作

    1. neutralize: position based 的alpha int neutralize(int di, int ti) { ; ; ; ; ii < nsyms; ++ii) { ...

  9. POJ 3660 Cow Contest ( 最短路松弛思想应用 && Floyd求传递闭包 )

    题意 : 给出 N 头奶牛在比赛的结果,问你最多的能根据给出结果确定其名次的奶牛头数.结果给出的形式为 A  B 代表在比赛当中 A 战胜了 B 分析 : 对于一头奶牛来说,如果我们能确定其他 N - ...

  10. Android keystore 密码找回

    昨天准备给自己的应用发布一个新版本,在apk打包时,发现之前的用的keystore密码忘了. 蛋碎了一地,我把我所能想到的密码都试了一遍(注:我平常在各个门户网站注册基本上用的都是那几个字母和数字组合 ...