用最短距离使几个球联通,最小生成树,两点距离为几何知识。
#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cmath>
using namespace std;
struct edge{
int x,y;
double v;
}e[20000];
int fa[200],am[200];
double ans;
struct circle{
double x,y,z,dis;
}c[200];
int len,n;
void init()
{
for(int i=0;i<n;i++)
{
fa[i] = i;
am[i] = 1;
}
}
int cmp(edge a,edge b)
{
return a.v<b.v;
}
int toGetFarther(int a)
{
while(fa[a]!=a)
a = fa[a];
return a;
}
void unin(int a,int b,int z)
{
int faA = toGetFarther(a),faB = toGetFarther(b);
if(fa[faA]!=fa[faB])
{
if(am[faA]>am[faB]){am[faA]+=am[faB];fa[faB] = faA;}
else {am[faB]+=am[faA];fa[faA] = faB;}
ans+=e[z].v;
}
}
double Kruskal()
{
ans = 0.0;
for(int i=0;i<len;i++)
unin(e[i].x,e[i].y,i);
return ans;
}
int main()
{
while(scanf("%d",&n)&&n)
{
init();
len = 0;
for(int i=0;i<n;i++)
scanf("%lf%lf%lf%lf",&c[i].x,&c[i].y,&c[i].z,&c[i].dis);
for(int i=0;i<n;i++)
for(int j=i+1;j<n;j++)
{
e[len].x = i;
e[len].y = j;
double dist = sqrt(pow(c[i].x-c[j].x,2.0)+pow(c[i].y-c[j].y,2.0)+pow(c[i].z-c[j].z,2.0))-(c[i].dis+c[j].dis);
if(dist>=0)e[len].v = dist;
else e[len].v = 0.0;
len ++;
}
sort(e,e+len,cmp);
printf("%.3f\n",Kruskal());
}
return 0;
}