题目链接:http://poj.org/problem?id=2031
题意:输入N 表示N个球心
下面N行,每行输入 x,y,z,r 表示球心的空间坐标 (x,y,z)以及球的半径r
求出球心距离 凡是俩球的球心距离小于这二者球半径和的 权值为0否则 权值为 r1+r2-L
给每个球心一个编号,G[i][j]表示编号i的球心到编号j的球心的距离
#include<cstdio>
#include<cmath>
#define oo 100000000
struct node
{
double x,y,z,r;
int i;
}f[101];
double low[101];
double G[101][101];
void calc(const node &a,const node &b){
double dis=sqrt(pow(a.x-b.x,2)+pow(a.y-b.y,2)+pow(a.z-b.z,2));
if(dis<a.r+b.r)
G[a.i][b.i]=G[b.i][a.i]=0;
else
G[a.i][b.i]=G[b.i][a.i]=dis-(a.r+b.r);
}
double prim(int n)
{
double ans=0,min;
bool vis[101]={0};
int pos=0,i,j;
for(int i=0;i<n;++i)
low[i]=G[0][i];
vis[pos]=true;
for(i=1;i<n;++i ){
for(j=0,min=low[j],pos=j;j<n;++j)if(!vis[j]){
if(low[j]<min){
min=low[j];
pos=j;
}
}
ans+=min;
vis[pos]=true;
for(j=0;j<n;++j){
if(!vis[j]&&low[j]>G[pos][j]){
low[j]=G[pos][j];
}
}
}
return ans;
}
int main()
{
int n;
while(scanf("%d",&n),n){
for(int i=0;i<n;++i){
scanf("%lf %lf %lf %lf",
&f[i].x,&f[i].y,&f[i].z,&f[i].r);
f[i].i=i;
}
for(int i=0;i<n;++i)
for(int j=0;j<n;++j)if(i==j)
G[i][j]=oo;
for(int j=0;j<n;++j)
for(int i=j+1;i<n;++i){
calc(f[j],f[i]);
}
printf("%.3lf\n",prim(n));
}
}