HDU 3405 poj 3771 最小生成树+删点
边数较少可以用Kruskal,因为Kruskal算法每次查找最短的边。 边数较多可以用Prim,因为它是每次加一个顶点,对边数多的适用。
用Prim。
#include<stdio.h> #include<string.h> #include<math.h> const double INF=99999; struct z{ int x,y; int cas; }node[300]; double xxx(int a,int b,int x,int y){ return sqrt((a-x)*(a-x)*1.0+(b-y)*(b-y)*1.0); } double small(double a,double b){ return a>b?b:a; } double mat[2000][2000]; double map[2000][2000]; double prim(int n){ int i,min_i,j; double Min,sum=0; double dis[3000]; int flag[3000]; for( i=1 ; i <=n ; i++ ) dis[i] = mat[i][1]; memset( flag, 0, sizeof(flag)); flag[1] = 1; for( i=2 ; i <=n ; i++ ) { Min = INF;min_i=i; for( j=2 ; j <=n ; j++ ){ if(flag[j]==0 && dis[j]<Min){ Min=dis[j]; min_i=j; } } if(Min==INF) break; sum += Min; flag[min_i] = 1; for( j=2 ; j <=n ; j++ ){ if(flag[j]==0 && dis[j]>mat[min_i][j]) dis[j] = mat[j][min_i]; } } return sum; } int main(){ int t,n,i,j,k; scanf("%d",&t); while(t--){ scanf("%d",&n); for(i=1;i<=n;i++){ scanf("%d %d",&node[i].x,&node[i].y); node[i].cas=i; } int num=0; for(i=1;i<=n;i++){ for(j=1;j<=n;j++){ mat[i][j]=INF; } } for(i=1;i<=n;i++){ for(j=1;j<=n;j++){ if(i==j) continue; int x=node[i].cas; int y=node[j].cas; map[x][y]=xxx(node[i].x,node[i].y,node[j].x,node[j].y); map[y][x]=xxx(node[i].x,node[i].y,node[j].x,node[j].y); num++; } } double ans=INF*2; for(i=1;i<=n;i++){ for(j=1;j<=n;j++){ for(k=1;k<=n;k++){ mat[j][k]=map[j][k]; } } for(j=1;j<=n;j++){ mat[j][i]=INF-1; mat[i][j]=INF-1; } ans=small(prim(n),ans); ans=ans; } printf("%.2lf\n",ans-INF+1); } }