看Prim算法之前要先知道什么是最小生成树。
对于一个如下的图,求最小生成树的权值。
首先定义一个数组map[N][N](N根据题目决定大小)存放权值。对其进行初始化:
0 | 1 | 2 | 3 | 4 | 5 | 6 | |
0 | – | – | – | – | – | – | – |
1 | – | ∞ | 5 | 8 | ∞ | ∞ | ∞ |
2 | – | 5 | ∞ | ∞ | 6 | 8 | ∞ |
3 | – | 8 | ∞ | ∞ | ∞ | 1 | ∞ |
4 | – | ∞ | 6 | ∞ | ∞ | 3 | 5 |
5 | – | ∞ | 8 | 1 | 3 | ∞ | 6 |
6 | – | ∞ | ∞ | ∞ | 5 | 6 | ∞ |
接下来随便选一个点当起始点,程序中一般选择第一个点。这里我们选择点1作为起始点
然后定义两个数组,lowValue[N],mark[N]。mark是用来标记该点是否已走过,没走过标记为1,走过标记为0。
选择1作起点后应把1标记,此时mark为:
1 | 2 | 3 | 4 | 5 | 6 |
0 | 1 | 1 | 1 | 1 | 1 |
而lowValue[i]表示已走过的点通往的点i的权值最小的路段权值。
1 | 2 | 3 | 4 | 5 | 6 |
0 | 5 | 8 | ∞ | ∞ | ∞ |
找出未走过的点即满足mark[i]==1时的最小值lowValue[i];此处i为2,lowValue[i]为5。
则标记2点为走过,更新mark:
1 | 2 | 3 | 4 | 5 | 6 |
0 | 0 | 1 | 1 | 1 | 1 |
由于map[2][4]为6,map[2][5]为8,更新lowValue[4]=6;lowValue[5]为8
1 | 2 | 3 | 4 | 5 | 6 |
0 | 5 | 8 | 6 | 8 | ∞ |
得到下图
找出未走过的点即满足mark[i]==1时的最小值lowValue[i];此处i为4,lowValue[i]为6。
则标记4点为走过,更新mark:
1 | 2 | 3 | 4 | 5 | 6 |
0 | 0 | 1 | 0 | 1 | 1 |
由于map[4][5]为3,map[4][6]为5,更新lowValue[5]=3;lowValue[6]为5
1 | 2 | 3 | 4 | 5 | 6 |
0 | 5 | 8 | 6 | 3 | 5 |
得到下图
找出未走过的点即满足mark[i]==1时的最小值lowValue[i];此处i为5,lowValue[i]为3。
则标记5点为走过,更新mark:
1 | 2 | 3 | 4 | 5 | 6 |
0 | 0 | 1 | 0 | 0 | 1 |
由于map[5][3]为1,map[5][6]为6,更新lowValue[3]=1。
1 | 2 | 3 | 4 | 5 | 6 |
0 | 5 | 1 | 6 | 3 | 5 |
得到下图
找出未走过的点即满足mark[i]==1时的最小值lowValue[i];此处i为3,lowValue[i]为1。
则标记3点为走过,更新mark:
1 | 2 | 3 | 4 | 5 | 6 |
0 | 0 | 0 | 0 | 0 | 1 |
lowValue:
1 | 2 | 3 | 4 | 5 | 6 |
0 | 5 | 1 | 6 | 3 | 5 |
得到下图
找出未走过的点即满足mark[i]==1时的最小值lowValue[i];此处i为6,lowValue[i]为5。
则标记6点为走过,更新mark:
1 | 2 | 3 | 4 | 5 | 6 |
0 | 0 | 0 | 0 | 0 | 0 |
lowValue:
1 | 2 | 3 | 4 | 5 | 6 |
0 | 5 | 1 | 6 | 3 | 5 |
得到下图
最后结果为lowValue中全部值的和20。
#include<stdio.h> int main() { int map[111][111],lowValue[111],mark[111]; int i,j,n,m,x,y,z,min,s,t,ans,max=999999999; while(scanf("%d%d",&n,&m),n){ for(i=1;i<=m;i++){ mark[i]=1; lowValue[i]=max; for(j=1;j<=m;j++){ map[i][j]=max; } } while(n--){ scanf("%d%d%d",&x,&y,&z); map[x][y]=map[y][x]=z; } ans=0; for(s=i=1;i<m;i++){ mark[s]=0; min=max; for(j=1;j<=m;j++){ if(mark[j]&&map[s][j]<lowValue[j]){ lowValue[j]=map[s][j]; } if(mark[j]&&min>=lowValue[j]){ min=lowValue[j]; t=j; } } if(min==max){ break; } s=t; ans+=min; } if(i==m){ printf("%d\n",ans); } else{ puts("?"); } } return 0; }
0 条评论。