【考研学习】最小生成树之

  • 普里姆算法其实就是结点优先算法,从图中任意一个结点开始,每次都找一个权值最小的边,将这两个结点连接起来,然后在生成的新整体中继续找一个权值最小的边,将新整体和最小边的终点连接起来,以此往复,直到所有的结点全部被包含进来。

图

以此图为例,假设从0开始生成,那么第一条权值最小的边就是(0,5)所以第一次的结果如下:

在这里插入图片描述
2. 接下来参考(0,5)这个整体(标红)权值最小的为(0,1)故第二次将(0,1)进行连接,以此类推。

最终结果为:
在这里插入图片描述

我们需要建立两个数组,vset[]——标识当前结点是否被并入到树中,lowcost[]——存放当前生成树到剩余各顶点的最短边的权值。

算法的流程
①将初始点v到其他顶点的所有边当作和候选边
②重复一下步骤
a)从候选边中选出权值最小的边输出,和该边的终点一起放入树中(vset置1)
b)检查所有剩余结点vi,如果(v,vi)的权值比lowcost[vi]小, 更新lowcost.

void Prim(MGraph g,int v0,int &sum)
{
	int lowcost[maxSize],vset[maxSize],v;
	int i,j,k,min;
	v=v0;			//将初始入树结点标识为v0
	for(i=0;i<g.n<++i)	//循环访问图中的所有边
	{
		lowcost[i]=g.edges[v0][i]; //将v0到剩余结点的权值存入
		vest[i]=0;	//入树标识全部置成0
	}
	vset[v0]=1;		//v0入树
	sum = 0;		//用来累计树的权值
	for(i=0;i<g.n-1;++i)
	{
		min = INF;	//INF可选一个比任意权值大的常量
		for(j=0;j<g;++j)
		{
			if(vset[j]==0&&lowcost[j]<min)
			{	//通过这个循环找到了最小权值
				min = lowcost[j];	
				k=j;
			}
		vset[k] = 1;	//当前最小权值入树
		v=k;
		sum+=min;
		for(j=0;j<g.n;++j)
			if(vset[j]==0&&g.edge[v][j]<lowcost[j])
				lowcost[j]=g.edges[v]
		}
	}
}