poj2031(最小生成树)

来源:互联网 发布:跑步的最佳时间知乎 编辑:程序博客网 时间:2024/04/29 18:25

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;}