最小生成树Prim算法实现

/************************ 

*

*	Author:Wang Yong

*	Blog:http://www.cnblogs.com/newwy

*

************************/

#include <iostream>

using namespace std;

#define MAXN 10000

#define INF  10000000



//无向图最小生成树,prim算法,邻接阵形式,复杂度O(n^2)

//返回最小生成树的长度,传入图的大小n和邻接阵mat,不相邻点边权inf

//可更改边权的类型,pre[]返回树的构造,用父结点表示,根节点(第一个)pre值为-1

//必须保证图的连通的!



void Prim(int n,int Graph[][MAXN],int * pre)

{

	int vset[MAXN],lowcost[MAXN];//lowcost[MAXN]表示存放顶点到为完成的生成树的最小权值

								//v[MAXN]表示该结点是否已经在生成树里 

	int i,j,k;				

	for(i = 0 ; i < n; i++)		//赋初始值,将每个结点的连接到生成树的权值赋值为最大,所有结点均未在生成树中

								//所有结点的前驱都是-1,表示没有任何结点与之相连 

	{lowcost[i] = INF;vset[i] = 0;pre[i] = -1;}

	

	for(lowcost[j = 0] = 0;j < n; j++)//分别将连通图中n个结点,加入到最小生成树中

	{

		for(k = -1,i = 0; i < n; i++)//第一次循环将k 赋值 -1,这样找到第一个没有加入到生成树中的结点,之后k值改变

		{							//继续循环,寻找不在生成树中的结点到生成树的权值最小的那个结点,将其链接到生成树上

			if(vset[i] == 0 &&(k == -1 || lowcost[i] < lowcost[k]))

				k = i;

		}

		printf("edge(%d,%d)的权值为%d,被加入生成树中\n",pre[k]+1,k+1,lowcost[k]);

		vset[k] = 1;				//将选中的结点做好标记 

		

		for(i = 0 ; i < n; i++)		//修正候选边,每次记录入选的结点k之后。分别记录其他结点到生成树的最小权值

		{

			if(vset[i] == 0 && Graph[k][i] < lowcost[i])

			{



				lowcost[i] = Graph[k][i];	

				pre[i] = k;				//pre记录i结点到生成树最小权值是连接在k结点上

			}

		} 

	} 

}

int mat[MAXN][MAXN],pre[MAXN];

int main()

{

	memset(mat,INF,sizeof(mat));

	int n;

	printf("请输入结点数目:");

	scanf("%d",&n);

	int i,j;

	printf("输入边的数目:");

	int en;

	scanf("%d",&en); 

	int a,b,cost;

	for(i = 0 ; i < en ;i++)

	{

		scanf("%d %d %d",&a,&b,&cost);

		--a;--b;

		mat[a][b] = mat[b][a] = cost;		

	}

	for(i = 0; i < n; i++)

	{

		for(j = 0 ; j < n ; j++)

			printf("%d ",mat[i][j]);

		printf("\n");

	}

	Prim(n,mat,pre);

	

} 

你可能感兴趣的:(最小生成树)