Agri-Net
Description
Input
Output
Sample Input
4 0 4 9 21 4 0 8 17 9 8 0 16 21 17 16 0
Sample Output
28
普里姆算法的分析:
从某一个点出发,找到与这个点相连的最小的边,加进来。把该边的另一个点包括进来,再从这两个点出发,找与之相连的最小的边。
继续加进来,继续这样做下去,直到找到n-1条边。
取图中任意一个顶点 u ∈ U作为生成树的根,之后往生成树上添加新的顶点 v ∈ V-U。
在添加的顶点 v和已经在生成树上的顶点u 之间必定存在一条边(u,v),并且该边的权值在所有连通顶点集U 和 V-U 之间的边中取值最小。
之后继续往生成树上添加顶点,直至生成树上U含有 n 个顶点为止。
普利姆算法的代码:
#include <stdio.h> #include <string.h> int map[110][110]; int vt[110]; int dis[110]; //从已知到未知点集路径权值 记录 int sum; void prim(int n) { int i, j; int pos; memset(vt, 0, sizeof(vt )); memset(dis, 0, sizeof(dis )); for(i=1; i<=n; i++) { dis[i] = map[1][i] ; } vt[1] = 1; int min; for(i=1; i<n; i++) { min = 10000000; for(j=1; j<=n; j++) { if(vt[j]==0 && dis[j] < min ) { min = dis[j] ; pos = j; } } sum = sum + min ; //权值被加入进来 vt[pos] = 1; //标记被访问 for(j=1; j<=n; j++) //更新权值数组 (这个步骤最好自己跑一下,否则不好理解 ) { if(vt[j]==0 && map[pos][j] < dis[j] ) { dis[j] = map[pos][j] ; } } } printf("%d\n", sum ); } int main() { int n, dd; int i, j; while(scanf("%d", &n)!=EOF) { //memset(vt, 0, sizeof(vt )); // memset(dis, 0, sizeof(dis )); sum = 0; for( i=1;i<=n;i++) { for( j=1;j<=n;j++) { map[i][j]=10000000; } } for(i=1;i<=n;i++) map[i][i]=0; for(i=1; i<=n; i++) { for(j=1; j<=n; j++) { scanf("%d", &dd); if(i!=j) { if(map[i][j] > dd) { map[i][j]=dd; map[j][i]=dd; } } } } prim(n); } return 0; }
原文:http://www.cnblogs.com/yspworld/p/3879979.html