概念引入:
(1)子图:从原图中选中一些定点和边组成的图,称为原图的子图。
(2)生成子图:选中一些边和所有定点组成的图,称为原图的生成子图。
(3)生成树:如果生成子图恰好是一棵树,则成为生成树。
(4)最先生成树:权值之和最小的生成树,则称为最小生成树。
所以最小生成树满足:1.权值最小,2.含有图中每一个结点。
最小生成树算法和前面学到的dijkstr求最短路径的算法及其相似,==
最短路径算法==-从原点出发-找到一个距离当前最近的结点(则该节点就是原点到该结点的最短距离)- 我们用这条边去跟新和其他结点的最短距离,下次再从剩下的未访问的结点中去选最小值,依次推倒下去每次找到的最小结点都是离原点最短距离。
*最小生成树算法-prim *(采用的是避圈法)-先找到离原点最近距离的结点i,再去找该结点到其他结点的距离比如将这些边值存入dist[]数组中,则这个数组中存储的是集合S到V-S集合的结点当然一维数组里面只能存储一个值,那么这个值就是具有最小值的结点,每次过滤dis[]数组中的值的时候我们需要选取的是最小的边值。
图解:从原点出发假设有三条边
这三条边分别是3->1, 3->4,3->5。
选择权值最小的一条边:
用红色箭头标记为以确定的边值。这样V集合里面有集合有V={3,5},用阴影标记出来。假设结点的全集为T则剩余结点为:T-V
则V与T-V直接的连线如下:
可以看到这之间有很多的线而,比如以4为结点的边有3->4,5->4而我们只会选择其中权值较小的一条,在和1,6进行比较。
找到权值最小的一条为5->6.
依次类推便可以得到所有的边:
数据结构:
T[][]临界矩阵存储图中的信息,S[]表示以选中的结点集合,lowcost[i]表是到i结点的权值最小的边,cost[i]表示i结点的前驱结点。
prim()函数,1.完成lowcost初始化,2.挑选出离集合T最近的定点x,3.x定点到其他定点的最小值更新lowcost[]。
代码如下:
#include <iostream>
#include <algorithm>
using namespace std;
#define INF 10000
const int maxn= 1000+5;
int T[maxn][maxn];//用于储存结点信息
bool s[maxn];//结点集合
int lowcost[maxn],costest[maxn];//lowcost表示到该结点的最短的边的权值,costest保存的是每个结点的前驱结点。
void Prim(int u0,int n)//u0:原点 n:结点个数
{
s[u0]=true;//原点标记为0
for (int i = 1; i <=n ; ++i)
{
if(i!=u0)
{
lowcost[i]=T[u0][i];
s[i]= false;
costest[i]=u0;
}
else
lowcost[i]=0;
}//完成初始化
//初始化要做的事情有:先将该结点到其他结点距离初始化给lowcost数组,将所有的结点的前驱标记为u0.
for (int i = 1; i <=n ; ++i) {
int temp = INF;
int t = u0;
for (int i1= 1; i1 <= n; i1++) {
if (!s[i1] && temp > lowcost[i1]) {
temp = lowcost[i1];
t = i1;
}
}//挑选集合S中最小的边的令一个结点
if (t == u0)
break;
s[t] = true;
for(int j=1;j<=n;j++)
{
if(!s[j]&&T[t][j]<lowcost[j])//该处便是与最短路径的差别之处
{
lowcost[j]=T[t][j];//更新出该结点到其他结点的最小距离
costest[j