最小生成树 prim算法

Prim算法的特点是集合A中的边总是形成单课树。prim算法的执行过程非常类似于寻找最短路径的Dijkstra算法。

树从图中的任意一个顶点r开始,使用贪心策略,每次选择添加到树中的边(一个顶点在树的结合V中,一个顶点在A-V中)都到尽量小。

算法:

1.初始化各个顶点到树的距离。(一开始树只有根节点)

	for(i=0;i<n;i++){
		closest[i]=m[root][i];
	}

2.找到一条离树最近的边,其一个点在集合V中,一个点在A-V中。

int min_ed=INT_MAX;
		for(i=0;i<n;i++){//find min edge
			if(visited[i]==0&&min_ed>closest[i]){
				min_ed=closest[i];
				pos=i;
			}
		}
3.将该边不在V中的顶点点加入到V中,若所有点都已经在V中,返回

		if(min_ed!=INT_MAX){//all edge is visited
			min_len+=min_ed;
			visited[pos]=1;
		}
		else
			return min_len;

4.更新不在V中的点,到树的距离。

		for(i=0;i<n;i++){//update 
			if(0==visited[i]&&m[pos][i]<closest[i])
				closest[i]=m[pos][i];
		}

5.执行步骤2.


Code:

int prim(int root,int n,int **m){
	if(m==NULL||n==0)
		return 0;
	int *closest=new int[n];
	int i,j;
	for(i=0;i<n;i++){
		closest[i]=m[root][i];
	}
	int *visited=new int[n];
	memset(visited,0,n*sizeof(n));
	visited[root]=1;
	int pos=root;
	int min_len=0;
	while(true){
		int min_ed=INT_MAX;
		for(i=0;i<n;i++){//find min edge
			if(visited[i]==0&&min_ed>closest[i]){
				min_ed=closest[i];
				pos=i;
			}
		}
		if(min_ed!=INT_MAX){//all edge is visited
			min_len+=min_ed;
			visited[pos]=1;
		}
		else
			return min_len;
		for(i=0;i<n;i++){//update 
			if(0==visited[i]&&m[pos][i]<closest[i])
				closest[i]=m[pos][i];
		}
	}
	return min_len;
}

例题:Agri-Net,最小生成树的直接应用: http://poj.org/problem?id=1258

#include<iostream>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<limits.h>
using namespace std;

int prim(int root,int n,int **m){
	if(m==NULL||n==0)
		return 0;
	int *closest=new int[n];
	int i,j;
	for(i=0;i<n;i++){
		closest[i]=m[root][i];
	}
	int *visited=new int[n];
	memset(visited,0,n*sizeof(n));
	visited[root]=1;
	int pos=root;
	int min_len=0;
	while(true){
		int min_ed=INT_MAX;
		for(i=0;i<n;i++){//find min edge
			if(visited[i]==0&&min_ed>closest[i]){
				min_ed=closest[i];
				pos=i;
			}
		}
		if(min_ed!=INT_MAX){//all edge is visited
			min_len+=min_ed;
			visited[pos]=1;
		}
		else
			return min_len;
		for(i=0;i<n;i++){//update 
			if(0==visited[i]&&m[pos][i]<closest[i])
				closest[i]=m[pos][i];
		}
	}
	return min_len;
}
int main()
{
	int n,i,j;
	while(scanf("%d",&n)!=EOF){
		int **m=new int* [n];
		for(i=0;i<n;i++){
			m[i]=new int [n];
			for(j=0;j<n;j++){
				int tmp;
				scanf("%d",&tmp);
				if(tmp!=0)
					m[i][j]=tmp;
				else
					m[i][j]=INT_MAX;
			}
		}
		int min_len=prim(0,n,m);
		printf("%d\n",min_len);
	}
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值