题目大意:在三维坐标中给出n个细胞的x,y,z坐标和半径r。如果两个点相交或相切则不用修路,否则修一条路连接两个细胞的表面,求最小生成树。
题目思路:最小生成树树模板过了,没啥说的
#include<cstdio> #include<cstdlib> #include<cmath> #include<iostream> #include<algorithm> #include<cstring> #include<vector> #include<queue> #define INF 0x3f3f3f3f #define MAX 1005 using namespace std; double x[MAX],y[MAX],z[MAX],r[MAX],Map[MAX][MAX],dist[MAX]; int n,vis[MAX]; double Dist(int a,int b)//计算两球心距离 { double k1=x[a]-x[b]; double k2=y[a]-y[b]; double k3=z[a]-z[b]; return sqrt(k1*k1+k2*k2+k3*k3); } void prm() { int i,j,k; double minn,sum=0; vis[1]=1; for(i=2;i<=n;i++) dist[i]=Map[1][i]; for(i=1;i<n;i++) { minn=INF; for(j=1;j<=n;j++) { if(!vis[j]&&dist[j]<minn) { minn=dist[j]; k=j; } } if(minn==INF) break; sum+=dist[k]; vis[k]=1; for(j=1;j<=n;j++) { if(Map[k][j]<dist[j] && !vis[j]) { dist[j]=Map[k][j]; } } } printf("%.3lf ",sum); } int main() { int i,j; while(scanf("%d",&n),n) { for(i=0;i<MAX;i++) for(j=0;j<MAX;j++) Map[i][j]=INF; memset(vis,0,sizeof(vis)); memset(dist,0,sizeof(dist)); for(i=1;i<=n;i++) { scanf("%lf%lf%lf%lf",&x[i],&y[i],&z[i],&r[i]); } for(i=1;i<=n;i++) { for(j=1;j<=n;j++) { if(i!=j) { double d=Dist(i,j); if(d>(r[i]+r[j])) { Map[i][j]=Map[j][i]=min(Map[i][j],(d-r[i]-r[j])); } else { Map[i][j]=Map[j][i]=0; } } } } prm(); } return 0; }