POJ 2031 Building a Space Station【kruskal】
题意: 给你N 个球,如果两个球球有重叠部分的话就称这两个球是联通的 ,如果两个球不想交,可以在他们之间建立一个桥梁,使其联通,问最少需要建多少长度的桥梁才能是全部的球联通。
分析: 图建好后就是最小生成树问题。
View Code
#include<stdio.h> #include<string.h> #include<stdlib.h> #include<math.h> int u[5005],v[5005],f[103],r[5005]; double w[5005]; int cmp(const void*p1,const void*p2) { return w[*(int*)p1]>w[*(int*)p2]?1:-1; } struct node { double x,y,z,r; }q[102]; int find(int x) { return f[x]==x?x:(f[x]=find(f[x])); } void join(int x,int y) { int fx=find(x); int fy=find(y); if(fx!=fy) { if(fx<fy) f[fy]=fx; else f[fx]=fy; } } int n,m; double kruskal() { double res=0; int i,e,fx,fy; for(i=0;i<m;i++) r[i]=i; qsort(r,m,sizeof(r[0]),cmp); for(i=0;i<m;i++) { e=r[i]; fx=find(u[e]); fy=find(v[e]); if(fx!=fy) { join(fx,fy); res+=w[e]; } } return res; } int main() { int i,j; double x; while(scanf("%d",&n),n) { m=0; for(i=0;i<n;i++) f[i]=i; for(i=0;i<n;i++) scanf("%lf%lf%lf%lf",&q[i].x,&q[i].y,&q[i].z,&q[i].r); for(i=0;i<n;i++) for(j=i+1;j<n;j++) { x=sqrt((q[i].x-q[j].x)*(q[i].x-q[j].x)+(q[i].y-q[j].y)*(q[i].y-q[j].y)+(q[i].z-q[j].z)*(q[i].z-q[j].z))-q[i].r-q[j].r; if(x<0.00000001) join(i,j); else { u[m]=i; v[m]=j; w[m++]=x; } } printf("%.3lf\n",kruskal()); } return 0; }