HDU 3405 World Islands 最小生成树变形
http://acm.hdu.edu.cn/showproblem.php?pid=3405
给出n个点,求把任意n-1个点连起来的最短路(n<50) ,开始不想把每个点都去一遍,因为那样就会构造n个最小生成树,怕超时。。。。有好多想法,如求出最小生成树在把书中最大的边去掉,但是这样可能把树分成两个部分,每部分点数都不是1。后来想用kruscal,把边从小到大加n-2条到树中,但是这样可能不会形成一个树。 最后还是把每个点都去一边,生n-1个最小生成树A掉的,对时间复杂度还是不了解啊 导致许多枚举,遍历等不敢做。 prim时间复杂度 O(n2)
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
const int inf=99999991;
using namespace std;
double map[55][55],dis[55];
int n;
bool vs[55];
struct Node
{
int x,y;
}node[55];
double Min(double a,double b)
{
if(a>b)return b;
else return a;
}
double prim(int x)
{
int i,k,mark;
memset(vs,0,sizeof(vs));
vs[x]=1;
for(i=0;i<n;i++)
{
dis[i]=map[i][0];
}vs[0]=1;
if(x==0)
{
for(i=0;i<n;i++){
dis[i]=map[i][1];
}vs[1]=1;
}
double MIN,SUM=0;
for(k=1;k<n-1;k++)
{
MIN=inf;
for(i=0;i<n;i++)
if(!vs[i]&&MIN>dis[i])
{
MIN=dis[i];
mark=i;
}
SUM+=MIN;
vs[mark]=1;
for(i=0;i<n;i++)
if(!vs[i]&&dis[i]>map[mark][i])
dis[i]=map[mark][i];
}
return SUM;
}
int main()
{
int i,j,CASE;
double d,x1,y1;
scanf("%d",&CASE);
while(CASE--)
{
scanf("%d",&n);
for(i=0;i<n;i++)
{
map[i][i]=0;
scanf("%d%d",&node[i].x,&node[i].y);
for(j=i-1;j>=0;j--)
{
x1=node[i].x-node[j].x;
y1=node[i].y-node[j].y;
d=sqrt(x1*x1+y1*y1);
map[i][j]=map[j][i]=d;
}
}
double h,g=inf;
for(i=0;i<n;i++)
{
h=prim(i);
g=Min(g,h);
}
printf("%.2lf\n",g);
}
return 0;
}

浙公网安备 33010602011771号