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);
	}
}


posted @ 2014-04-30 09:42  kewowlo  阅读(270)  评论(0编辑  收藏  举报