POJ 2031Building a Space Station

题意:就是给出三维坐标系上的一些球的球心坐标和其半径,搭建通路,使得他们能够相互连通。如果两个球有重叠的部分则算为已连通,无需再搭桥。求搭建通路的最小费用,最小生成树板子题,细心处理数据即可;

#include<algorithm>
#include<iostream>
#include<queue>
#include<stack>
#include<vector>
#include<map>
#include<set>
#include<cstring>
#include<string>
#include<cstdio>
#include<cmath>
using namespace std;
typedef struct node{
	int x;int y;double date;
}node;
typedef struct list{
	double a;double b;double c;double d;
}list;
bool cmp(node e,node r){
	return e.date<r.date;
}
int first[115];int next[115];
void csh(int m){
	for(int i=1;i<=m;i++){
		first[i]=i;
		next[i]=1;
	}
	return ;
} 
int find(int x){
	if(x==first[x])  return x;
	else{
		x=first[x];
		return find(x);
	}
}
void hebin(int x,int y){
	x=find(x);
	y=find(y);
	if(x==y) return ;
	else{
		if(next[x]>next[y]){
			first[y]=x;
		}
		else{
			first[x]=y;
			if(next[x]==next[y]){
				next[y]++;
			}
		}
	}
	return ;
}
list aa[115];
node vulue[20010];
int main(){
	int m;
	while(scanf("%d",&m)==1&&m!=0){
		for(int i=1;i<=m;i++){
			scanf("%lf %lf %lf %lf",&aa[i].a,&aa[i].b,&aa[i].c,&aa[i].d);
		}
		int ans=0;
		int u=0;
		csh(m);
		for(int i=1;i<m;i++){
			for(int j=i+1;j<=m;j++){
				double t;
				t=1.0*sqrt((aa[j].a-aa[i].a)*(aa[j].a-aa[i].a)+(aa[j].b-aa[i].b)*(aa[j].b-aa[i].b)+(aa[j].c-aa[i].c)*(aa[j].c-aa[i].c))-aa[i].d-aa[j].d;
				if(t<=0){
					if(find(i)!=find(j)){
						ans++;
					hebin(i,j);}
				}
				else{
					u++;
				vulue[u].x=i;vulue[u].y=j;vulue[u].date=t;	
				}
			}
		}
		sort(vulue+1,vulue+u+1,cmp);
		double sum=0;
		for(int i=1;i<=u;i++){
			if(find(vulue[i].x)!=find(vulue[i].y)){
				ans++;
				sum+=vulue[i].date;
				hebin(vulue[i].x,vulue[i].y);
				if(ans==(m-1)){
					break;
				}
			}
		}
		printf("%.3lf\n",sum);
	}
	return 0;
}


posted @ 2017-10-03 20:25  wang9897  阅读(101)  评论(0编辑  收藏  举报