POJ 2031 Building a Space Station【kruskal】

题意: 给你N 个球,如果两个球球有重叠部分的话就称这两个球是联通的 ,如果两个球不想交,可以在他们之间建立一个桥梁,使其联通,问最少需要建多少长度的桥梁才能是全部的球联通。

分析: 图建好后就是最小生成树问题。

View Code
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<math.h>
int u[5005],v[5005],f[103],r[5005];
double w[5005];
int cmp(const void*p1,const void*p2)
{
    return w[*(int*)p1]>w[*(int*)p2]?1:-1;
}
struct node
{
    double x,y,z,r;
}q[102];
int find(int x)
{
    return f[x]==x?x:(f[x]=find(f[x]));
}
void join(int x,int y)
{
    int fx=find(x);
    int fy=find(y);
    if(fx!=fy)
    {
        if(fx<fy)
            f[fy]=fx;
        else f[fx]=fy;
    }
}
int n,m;
double kruskal()
{
    double res=0;
    int i,e,fx,fy;
    for(i=0;i<m;i++)
        r[i]=i;
    qsort(r,m,sizeof(r[0]),cmp);
    for(i=0;i<m;i++)
    {
        e=r[i];
        fx=find(u[e]);
        fy=find(v[e]);
        if(fx!=fy)
        {
            join(fx,fy);
            res+=w[e];
        }
    }
    return res;
}
int main()
{
    int i,j;
    double x;
    while(scanf("%d",&n),n)
    {
        m=0;
        for(i=0;i<n;i++)
             f[i]=i;
        for(i=0;i<n;i++)
            scanf("%lf%lf%lf%lf",&q[i].x,&q[i].y,&q[i].z,&q[i].r);
        for(i=0;i<n;i++)
            for(j=i+1;j<n;j++)
            {
                x=sqrt((q[i].x-q[j].x)*(q[i].x-q[j].x)+(q[i].y-q[j].y)*(q[i].y-q[j].y)+(q[i].z-q[j].z)*(q[i].z-q[j].z))-q[i].r-q[j].r;
                if(x<0.00000001)
                    join(i,j);
                else {
                    u[m]=i;
                    v[m]=j;
                    w[m++]=x;
                }
            }
        printf("%.3lf\n",kruskal());
    }
    return 0;
}

 

posted @ 2012-04-22 10:36  'wind  阅读(158)  评论(0编辑  收藏  举报