所谓最小生成树就是给定一个无向图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; }