题意:给全村建光纤,求花费最小
思路:最小生成树,树相对于图来说就是没有环
- m用来存图 v判断是否访问 low用来存两点间的最短距离
- 给low赋值 for(i=1;i<=n;i++){if(i!=pos) low[i]=m[pos][i] else low[i]=0;}
- 找最小值 即找顶点i的最小距离 for(int j=1;j<n;j++) for(int i=1;i<=n;i++) if(v[i]==0&&min>l[i]) min=l[i] pos=i;
- 更新权值
for(j = 1; j <= n; j++) //更新权值 if(visited[j]==0 && low[j]>m[pos][j]) low[j] = m[pos][j];
解决问题的代码:
#include <stdio.h> #include <string.h> #define INF 0x3f3f3f3f #define MAXN 517 //创建m二维数组储存图表,low数组记录每2个点间最小权值,visited数组标记某点是否已访问 int m[MAXN][MAXN], low[MAXN], visited[MAXN]; int n; int prim( ) { int i, j; int pos, minn, result=0; memset(visited,0,sizeof(visited)); visited[1] = 1; pos = 1; //从某点开始,分别标记和记录该点 for(i = 1; i <= n; i++) //第一次给low数组赋值 if(i != pos) low[i] = m[pos][i]; else low[i] = 0; for(i = 1; i < n; i++) //再运行n-1次 { minn = INF; //找出最小权值并记录位置 for(j=1; j<=n; j++) { if(visited[j]==0 && minn>low[j]) { minn = low[j]; pos = j; } } result += minn; //最小权值累加 visited[pos] = 1; //标记该点 for(j = 1; j <= n; j++) //更新权值 if(visited[j]==0 && low[j]>m[pos][j]) low[j] = m[pos][j]; } return result; } int main() { int i,j,ans; while(scanf("%d",&n)!=EOF) { memset(m,INF,sizeof(m)); //所有权值初始化为最大 for(i = 1; i <= n; i++) for(j = 1; j <= n; j++) { scanf("%d",&m[i][j]); } ans=prim( ); printf("%d\n",ans); } return 0; }