POJ 2031(最小生成树Kruskal算法+几何判断)

题目:给你n,接下来n行每行四个数,空间坐标x ,y,z和半径,求最小生成树

思路:根据空间坐标半径,求出各个球(可以看成球)重不重叠,重叠就用并查集搞一下,然后数据搞成边的结构体形式,就是道简单最小生成树了

#include <iostream>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <string>
#include <map>
#include <iomanip>
#include <algorithm>
#include <queue>
#include <stack>
#include <set>
#include <vector>
//const int maxn = 1e5+5;
#define ll long long
#define lowbit(x) x&(-x)
ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
ll lcm(ll a,ll b){return a/gcd(a,b)*b;}

#define MAX INT_MAX
#define FOR(i,a,b) for( int i = a;i <= b;++i)
#define bug cout<<"--------------"<<endl
using namespace std;
int n,m,tail;
double ans;
int pre[11000];
struct node
{
    double x,y,z;
}edge[11000];
struct hhh
{
    double x,y,z,r;
}v[11000];
double cmp(node a,node b)
{
    if(a.z!=b.z)
    return a.z<b.z;
    if(a.x!=b.x)
        return a.x<b.x;
    return a.y>b.y;
}
int Find(int x)
{
    if(pre[x]==x) return x;
    return Find(pre[x]);
}
double dis(int a,int b)
{
    double temp=(v[a].x-v[b].x)*(v[a].x-v[b].x)+(v[a].y-v[b].y)*(v[a].y-v[b].y)+(v[a].z-v[b].z)*(v[a].z-v[b].z);
    temp=sqrt(temp);
    if(temp<=v[a].r+v[b].r) return 0;
    return temp-v[a].r-v[b].r;

}
void besame(int x,int y)
{
    int fx=Find(x);
    int fy=Find(y);
    if(fx!=fy)  pre[fy]=fx;
}
void clearr()
{
    tail=0;
    ans=0;
    FOR(i,1,n) pre[i]=i;
}
int main()
{
    while(scanf("%d",&n))
    {
        if(n==0) break;
        clearr();

        FOR(i,1,n) cin>>v[i].x>>v[i].y>>v[i].z>>v[i].r;

        FOR(i,1,n-1)   //小号为头
        {
            FOR(j,i+1,n)
            {
                if(dis(i,j)==0) besame(i,j);
                else
                {
                    edge[++tail].x=i;
                    edge[tail].y=j;
                    edge[tail].z=dis(i,j);
                }

            }
        }
        sort (edge+1,edge+1+tail,cmp);
        FOR(i,1,tail)
        {
            int fx=Find(edge[i].x);
            int fy=Find(edge[i].y);
            if(fx==fy) continue;
            pre[fy]=fx;
            ans+=edge[i].z;
        }
        cout<<fixed<<setprecision(3)<<ans<<endl;
    }

}

 

  

posted @ 2019-08-03 01:30  阿斯水生产线  阅读(526)  评论(0编辑  收藏  举报