题解 最小生成树 prim算法
Problem Description
省政府“畅通工程”的目标是使全省任何两个村庄间都可以实现公路交通(但不一定有直接的公路相连,只要能间接通过公路可达即可)。经过调查评估,得到的统计表中列出了有可能建设公路的若干条道路的成本。现请你编写程序,计算出全省畅通需要的最低成本。
Input
测试输入包含若干测试用例。每个测试用例的第1行给出评估的道路条数 N、村庄数目M ( < 100 );随后的 N
行对应村庄间道路的成本,每行给出一对正整数,分别是两个村庄的编号,以及此两村庄间道路的成本(也是正整数)。为简单起见,村庄从1到M编号。当N为0时,全部输入结束,相应的结果不要输出。
Output
对每个测试用例,在1行里输出全省畅通需要的最低成本。若统计数据不足以保证畅通,则输出“?”。
Sample Input
3 3
1 2 1
1 3 2
2 3 4
1 3
2 3 2
0 100
Sample Output
3
?
//这个讲的很nice! http://www.cnblogs.com/Veegin/archive/2011/04/29/2032388.html
1 #include<stdio.h> 2 #include<string.h> 3 #define N 1000 4 #define MAXINT 999999 5 //创建map二维数组储存图表,low数组记录每2个点间最小权值,visited数组标记某点是否已访问 6 int visit[N],map[N][N],low[N]; 7 int m; 8 9 int prim() 10 { 11 int i,j,pos,min; 12 memset(visit,0,sizeof(visit)); 13 //从某点开始,分别标记和记录该点 14 visit[1]=1; 15 pos=1; 16 //第一次给low数组赋值 17 for(i=1;i<=m;i++) 18 { 19 if(i!=pos) 20 low[i]=map[pos][i]; 21 } 22 int result=0; 23 //再运行n-1次 24 for(i=1;i<m;i++) 25 { 26 //找出最小权值并记录位置 27 min=MAXINT; 28 for(j=1;j<=m;j++) 29 { 30 if(visit[j]==0&&min>low[j]) 31 { 32 min=low[j]; 33 pos=j; 34 } 35 } 36 if(min==MAXINT) return 0; 37 //最小权值累加 38 result+=min; 39 //标记改点 40 visit[pos]=1; 41 //更新权值 42 for(j=1;j<=m;j++) 43 { 44 if(visit[j]==0&&low[j]>map[pos][j]) 45 { 46 low[j]=map[pos][j]; 47 } 48 } 49 } 50 return result; 51 } 52 53 int main() 54 { 55 int n,a,b,v,ans,i; 56 while(~scanf("%d",&n)&&n) 57 { 58 //所有权值初始化为最大 59 memset(map,MAXINT,sizeof(map)); 60 scanf("%d",&m); 61 for(i=1;i<=n;i++) 62 { 63 scanf("%d %d %d",&a,&b,&v); 64 map[a][b]=map[b][a]=v; 65 } 66 ans=prim(); 67 if(ans) 68 printf("%d ",ans); 69 else 70 puts("?"); 71 } 72 return 0; 73 }