所谓最小生成树就是给定一个无向图G = (V, E) 中,G是无向图中所有顶点和边的集合,(u, v) 代表连接顶点 u 与顶点 v 的边,而 w(u, v) 代表此边的权重,若存在 T 为 E 的子集且为无循环图,使得 w(T) 最小,则此 T 为 G 的最小生成树。
而Prime算法就是在无向图中来寻找这样一颗最小生成树。
思想:
1 先选取第一个顶点,然后找出第一个顶点到其他顶点的最小值,然后标记最小值的路径已走过,加入该顶点;2计算现有顶点到其他顶点的最小值,更新最小值列表,找出最小值列表中的最小值,标记路径,加入顶点;3重复以上过程,直到所有顶点都加入;
这个题目就是赤裸裸的Prime算法。以题目中给出的样例来模拟程序执行的过程:
如图所示:先选取1顶点,1顶点到各顶点的最小距离为dis[2]=4,dis[3]=9,dis[4]=21,最小值为4,所以第二个顶点选取顶点2加入,顶点2到顶点3的距离为8<顶点1到顶点3的距离9,所以把9替换为8,即dis[3]=8,同样可替换dis[4]=17,这样下一个加入的顶点为3,然后顶点3到顶点4的距离为16<顶点2到顶点4的距离17,所以dis[4]=16。即为一下过程:
代码如下:
/*
ID: supersnow0622
PROG: agrinet
LANG: C++
*/
#include <iostream>
#include <fstream>
#include <string>
#include<memory.h>
using namespace std;
int visit[101],mindis[101];
int data[101][101];
int prime(int cost[][101],int num)
{
int min,node,sum=0;
memset(visit,0,sizeof(visit));
visit[0]=1;
for(int i=0;i<num;i++)
mindis[i]=cost[0][i];
for(int i=1;i<num;i++)
{
min=10000000;
node=-1;
for(int j=1;j<num;j++)
if(visit[j]==0&&mindis[j]<min)
{
min=mindis[j];
node=j;
}
// if(min==10000000)return -1;
visit[node]=1;
sum+=min;
for(int j=1;j<num;j++)
if(visit[j]==0&&mindis[j]>cost[node][j])
mindis[j]=cost[node][j];
}
return sum;
}
int main() {
ofstream fout ("agrinet.out");
ifstream fin ("agrinet.in");
int N;
cin>>N;
for(int i=0;i<N;i++)
for(int j=0;j<N;j++)
cin>>data[i][j];
cout<<prime(data,N);
return 0;
}