题目链接:http://poj.org/problem?id=2031
题意:给你n个球,让你用最小的花费,把这n个球联通,如果两个球相交,就默认联通,否者连接这两个球的花费就是,球面之间的最短距离,输出最小花费
解析:最小生成树裸题
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <cmath>
using namespace std;
const int maxn = 1e5+100;
struct node
{
int u,v;
double c;
node() {}
node(int _u,int _v,double _c)
{
u = _u;
v = _v;
c = _c;
}
bool operator < (const node &b)const
{
return c<b.c;
}
}res[maxn];
struct point
{
double x,y,z,r;
}a[105];
int fa[105];
double dis(point p1,point p2)
{
return sqrt((p1.x-p2.x)*(p1.x-p2.x)+
(p1.y-p2.y)*(p1.y-p2.y)+
(p1.z-p2.z)*(p1.z-p2.z));
}
int getfa(int x)
{
if(fa[x]==x)
return fa[x];
return fa[x] = getfa(fa[x]);
}
int main(void)
{
int n;
while(~scanf("%d",&n)&&n)
{
for(int i=1;i<=n;i++)
{
scanf("%lf %lf %lf %lf",&a[i].x,&a[i].y,&a[i].z,&a[i].r);
fa[i] = i;
}
int cnt = 0;
for(int i=1;i<=n;i++)
{
for(int j=i+1;j<=n;j++)
{
double d = dis(a[i],a[j])-a[i].r-a[j].r;
res[cnt++] = node(i,j,max(d,0.0));
}
}
double ans = 0;
sort(res,res+cnt);
for(int i=0;i<cnt;i++)
{
int t1 = getfa(res[i].u);
int t2 = getfa(res[i].v);
if(t1!=t2)
{
ans += res[i].c;
fa[t1] = t2;
}
}
printf("%.3f\n",ans);
}
return 0;
}