http://poj.org/problem?id=2031
这题被分到计算几何中了,是挺简单的最小生成树,把细胞当成图中的点,各点之间的边权 = 细胞间的距离-两细胞的半径
再套最小生成树的模板就OK了
#include <iostream>
#include<cstdio>
#include<cstring>
#include<stdlib.h>
#include<cmath>
#include<algorithm>
using namespace std;
typedef struct node
{
double x,y,z,r,d;
}point;
struct mode
{
int a,b;
double dd;
}w[11000];
point p[1010];
int father[1100];
int find(int x)
{
if(x!=father[x])
father[x] = find(father[x]);
return father[x];
}
double dd(point a,point b)
{
return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)+(a.z-b.z)*(a.z-b.z));
}
bool cmp(mode a,mode b)
{
return a.dd<b.dd;
}
int main()
{
int i,j,n;
while(cin>>n)
{
if(n==0)
break;
int g = 0;
for(i = 1; i <= n ; i++)
cin>>p[i].x>>p[i].y>>p[i].z>>p[i].r;
for(i = 1; i <= n ; i++)
father[i] = i;
for(i = 1 ; i <= n ; i++)
{
for(j = i+1 ; j <= n; j++)
{
double dis = dd(p[i],p[j])-(p[i].r+p[j].r);
g++;
if(dis>0)
{
w[g].a = i;
w[g].b = j;
w[g].dd = dis;
}
else
{
w[g].a = i;
w[g].b = j;
w[g].dd = 0.0;
}
}
}
sort(w+1,w+g+1,cmp);
int num = 0;
double sum = 0.0;
for(i = 1 ;i <= g&&num<n-1 ; i++)
{
int tx = find(w[i].a);
int ty = find(w[i].b);
double td = w[i].dd;
if(tx!=ty)
{
sum+=td;
num++;
father[tx] = ty;
}
}
printf("%.3lf\n",sum);
}
return 0;
}