POJ 3771 World Islands
题目链接:http://poj.org/problem?id=3771
题意:有n个点,去掉一个点,在n-1个点中建n-2条边。使建边的总长度最小。
思路:暴力枚举删去每个点的最小总边长度
#include<stdio.h>
#include<math.h>
#include<string.h>
const double inf=999999.0;
struct node
{
int x,y;
};
struct node p[300];
double dis(node a,node b)
{
return sqrt(1.0*((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)));
}
double map[60][60];
double Prim(int n,int k)
{
int i,j,min_i;
double min,sum=0;
double dis[501];
int vis[501];
int t=k+1>=n? 0:k+1;//改变起始点。
for(i=0;i<n;i++)
{
if(i!=k)//去掉 包含删去点边
{
dis[i]=map[i][t];
vis[i]=false;
}
}
vis[k]=true;
dis[k]=inf;
vis[t]=false;
dis[t]=0;
for(i=0;i<n-1;i++)
{
min=inf,min_i=i;
for(j=0;j<n;j++)
{
if(vis[j]==false && dis[j]<min)
{
min=dis[j];
min_i=j;
}
}
if(min==inf)
break;
sum+=min;
vis[min_i]=true;
for(j=0;j<n;j++)
{
if(vis[j]==false && dis[j]>map[min_i][j])
dis[j]=map[min_i][j];
}
}
return sum;
}
int main()
{
int t;
int i,j,n;
while(scanf("%d",&t)!=EOF)
{
while(t--)
{
scanf("%d",&n);
for(i=0;i<n;i++)
scanf("%d %d",&p[i].x,&p[i].y);
for(i=0;i<n;i++)
{
for(j=0;j<n;j++)
{
if(i!=j)
map[i][j]=dis(p[i],p[j]);
else
map[i][j]=0;
}
}
double min=inf,ans;
for(i=0;i<n;i++)
{
ans=Prim(n,i);
if(min>ans)
min=ans;
}
printf("%.2lf\n",min);
}
}
return 0;
}