最小生成树 prim hdu 1233
hdu 1233 还是畅通工程
昨天晚上看到了羽哥做这道题,加上昨天培训过,我就开始决定码这道最小生成树的题,本来想用prim和kursal(并查集)都写一遍呢,果断被坑了,对prim了解不深,把他当成了有向图图了,导致做错了,
1:注意 prim用邻接矩阵存储,采用的是无向图的存储方式;
2:寻找到的最短边到点的路径如果比dis值小的话,直接赋值;
下面采用了两种方法;
方法一:直接求最短路径的长度:
post code:
#include<stdio.h> #include<string.h> const int MAX=999999999; int a[120][120]; int dis[120]; int min; int node; struct Cnode{ int x,y; }road[120]; int main() { int n,m,i,x,y,d,j,len,ji,k,sum; while(scanf("%d",&n)&&n!=0) { sum=0; len=0; ji=1; m=n*(n-1)/2; memset(a,0,sizeof(a)); for(i=1;i<=m;i++) { scanf("%d %d %d",&x,&y,&d); //构建无向图的邻接矩阵 important a[x][y]=d; a[y][x]=d; } for(i=1;i<=n;i++) //以1为起始点 开始进行prim { dis[i]=a[1][i]; } for(i=2;i<=n;i++) { min=MAX; for(j=2;j<=n;j++) { if(dis[j]!=0) {if(dis[j]<min){min=dis[j];node=j;} } // 找到dis中不是0的最小值, } dis[node]=0; sum+=min; for(k=2;k<=n;k++) { if(a[node][k]!=0&&dis[k]!=0){if(a[node][k]<dis[k]){dis[k]=a[node][k];} } // 对其中的dis值进行替换 } } printf("%d\n",sum); } }
方法二:将最短路径的点求出,再累加:
#include<stdio.h> #include<string.h> const int MAX=999999999; int a[120][120]; struct node { int x,y,d; } dis[120]; int min; int node; struct Cnode{ int x,y; }road[120]; int main() { int n,m,i,x,y,d,j,len,ji,k,sum; while(scanf("%d",&n)&&n!=0) { sum=0; len=0; ji=1; m=n*(n-1)/2; memset(a,0,sizeof(a)); for(i=1;i<=m;i++) { scanf("%d %d %d",&x,&y,&d); a[x][y]=d; a[y][x]=d; } for(i=2;i<=n;i++) { dis[i].d=a[1][i]; dis[i].x=1; dis[i].y=i; } for(i=2;i<=n;i++) { min=MAX; for(j=2;j<=n;j++) { if(dis[j].d!=0) {if(dis[j].d<min){min=dis[j].d;node=j; }} } dis[node].d=0; road[ji].x=dis[node].x; //存储连接的点 及最小路径的点 road[ji].y=dis[node].y; ji++; for(k=2;k<=n;k++) { if(a[node][k]!=0&&dis[k].d!=0){if(a[node][k]<dis[k].d){dis[k].d=a[node][k];dis[k].x=node;} } //将点的改变记入在dis结构体中 } } for(i=1;i<ji;i++) //遍历所有的最小路径的点,即可求出最小生成树的距离。 { sum+=a[road[i].x][road[i].y]; } printf("%d\n",sum); } }