题目链接:
http://write.blog.youkuaiyun.com/postedit?ref=toolbar
题意:
在三维空间中有N个球形空间站,给出每个空间站的三维坐标x,y,z 和半径.其中空间站之间可能存在相交,包含,相离等情况。如果非相离则两空间站的距离为0。求连同所有空间站的最小生成树。
题解:
三维构图两空间站的距离等于两圆心距离减去两圆的半径 如果距离小于0,则距离为0
在套kruskal模板即可
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
struct node
{
int u,v;
double w;
} edge[10005];
double map[105][4],ans;
int fa[105];
int m,s;
int cmp(node a,node b)
{
return a.w<b.w;
}
int find(int x)
{
int d=x,t;
while(fa[d]>=0)
d=fa[d];
while(x!=d) //压缩路径
{
t=fa[x];
fa[x]=d;
x=t;
}
return d;
}
void Kruskal()
{
int r1,i,j,r2,n=0,ss;
for(i=0; i<s; i++)
{
r1=find(edge[i].u),r2=find(edge[i].v);
if(r1!=r2)
{
n++;
ss=fa[r1]+fa[r2];
ans+=edge[i].w;
if(fa[r1]<fa[r2])
fa[r1]=ss,fa[r2]=r1;
else
fa[r1]=r2,fa[r2]=ss;
}
if(n==m-1)
break;
}
return;
}
int main()
{
int i,j;
double weight;
while(scanf("%d",&m)&&m)
{
ans=s=0;
memset(fa,-1,sizeof(fa));
for(i=1; i<=m; i++)
{
scanf("%lf%lf%lf%lf",&map[i][0],&map[i][1],&map[i][2],&map[i][3]);
for(j=1; j<i; j++)
{
edge[s].u=j,edge[s].v=i;
weight=sqrt(pow(map[i][0]-map[j][0],2)+pow(map[i][1]-map[j][1],2)+pow(map[i][2]-map[j][2],2));
if(weight>map[i][3]+map[j][3]) //距离
edge[s++].w=weight-map[i][3]-map[j][3];
else
edge[s++].w=0;
}
}
sort(edge,edge+s,cmp);
Kruskal();
printf("%.3lf\n",ans);
}
return 0;
}