原来是求二维数组的每行或者每列的最小值,不过需要主要的是如果是4个点,只需要3条边就可以完全连接起来了,所以只需要找3次就行了。4条边有一条边会重复,需要舍弃。
就用题目的测试数据比较,用二维数组保存点与点连接的距离。
就用i代表行,j代表列。会发现 i,j都是从第二行开始的。而且跟y=x 直线对称。为什么说只要找到每行或者每列的最小值就行了呢。假设最开始没有2这个点,此时1,3,4就是一个集合。然后新添加一个点2进去,此时的最短路径就是点2到这个集合的最短路径,然后看2能够跟集合里面的哪些点连接,测试数据表示能看出来跟1,3,4都连接,所以找出与1,3,4连接的最小值就行,就能够构成一个新的最小生成树。然后比较过一个就标记下,不再重复找,接下来代码就简单了。
//因为每个楼都在最小生成树中,因此无论从哪号楼拉线都没有区别,所以只要选最小那个值就行 #include<stdio.h> #include<stdlib.h> #include<string.h> #define inf 0x7FFFFFFF/*就是INT_MAX,四个字节,共32位,而每四位为一个十六进制为,因为存在计算机中为补码,所以最高四位是0111,即7*/ int map[501][501];//**二维数组标记地图**// bool a[501]; int cmp(const void *a,const void *b) { return *(int *)a-*(int *)b; } int main() { int T,m,n;int i,j,k;int min,t,x,y,value,ans;int b[501];//**用一维数组a[i]用来标记第i个点是否被访问过**// scanf("%d",&T); while(T--) { memset(b,0,sizeof(b)); scanf("%d %d",&m,&n); ans=0; for(i=1;i<=m;i++) for(j=1;j<=m;j++) map[i][i]=inf; for(i=1;i<=n;i++) { scanf("%d %d %d",&x,&y,&value); map[x][y]=map[y][x]=value;//**把能够连接的线都用二维数组保存,并将二维数组赋值**// } for(i=0;i<m;i++) scanf("%d",&b[i]);//**无论从哪号楼拉线都没有区别,所以只要选最小那个值就行**// qsort(b,m,sizeof(int),cmp); for(i=2;i<=m;i++) a[i]=false; a[1]=true;//**访问过了,标记true,表示不再访问**// for(i=2;i<=m;i++)//**标记了就知道,i,j都是从2开始,并对称**// { min=inf; for(j=2;j<=m;j++) { if(min>map[i][j]&&!(a[j]==true&&a[i]==true))//**找出最小权值,避免环路**// { min=map[i][j]; k=j; } } // for(j=2;j<=m;j++)//**为下一次循环做准备,重新初始化**// // a[j]=false; a[k]=true; if(min!=inf) ans=ans+min;//**加上权值**// //printf("%d\n",ans); } printf("%d\n",ans+b[0]); system("pause"); } return 0; }
时间: 2024-11-08 23:07:40