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;
}