POJ 2031

题意:给你一些球体的属性:球心坐标x,y,z  半径  这些球体构成了图,各个球之间的边权等于两个球的距离,求最小生成树。

建好图之后,就用最小生成树做就好。

代码:

#include<iostream>
#include<queue>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define INF 0x3f3f3f3f
using namespace std;

int n;
struct node
{
    double x;double y;double z;double r;
}point[205];

double map[200][200];

double dis(int i,int j)
{
    double a=point[i].x-point[j].x;
    double b=point[i].y-point[j].y;
    double c=point[i].z-point[j].z;
    return sqrt(a*a+b*b+c*c);
}

double cross(int i,int j)
{
    double k=point[i].r+point[j].r;
    double d=dis(i,j);
    if(d>k)
    {
        return d-k;
    }
    return 0;
}

void tree()
{
    double s[200];
    int vis[200];
    memset(vis,0,sizeof(vis));
    for(int i=1;i<n;i++)
    {
        s[i]=map[0][i];
    }
    vis[0]=1;
    int l;
    double sum=0;
    for(int i=0;i<n-1;i++)//这个地方一定是n-1,因为总共要找n-1条边。
    {
        double min1=INF;
        for(int j=0;j<n;j++)
        {
            if(!vis[j]&&s[j]<min1)
            {
                min1=s[j];
                l=j;
            }
        }
        vis[l]=1;
        sum+=min1;
        for(int j=0;j<n;j++)
        {
            if(!vis[j]&&map[l][j]<s[j])
            {
                s[j]=map[l][j];
            }
        }
    }
    printf("%.3f
",sum);
}
int main()
{
    while(~scanf("%d",&n)&&n)
    {
        for(int i=0;i<n;i++)
        {
            scanf("%lf%lf%lf%lf",& point[i].x,& point[i].y,&point[i].z,& point[i].r);
        }
        memset(map,0,sizeof(map));
        for(int i=0;i<n;i++)
        {
            for(int j=i+1;j<n;j++)
            {
                map[i][j]=map[j][i]=cross(i,j);
            }
        }
        tree();
    }
    return 0;
}
原文地址:https://www.cnblogs.com/qioalu/p/5202838.html