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

  

posted @ 2012-03-31 21:24  快乐.  阅读(423)  评论(0编辑  收藏  举报