最小生成树的模板题。prim和kuruskal都能够。可是要注意精度损失。
题意:给定一个三维坐标系。给定一些圆的圆心坐标,和半径。求出全部圆心构成的最小生成树;
特别注意:两个圆假设相交在一起,算做联通,距离为0;
C++提交
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> #define INF 1e7 using namespace std; struct node { double x,y ,z, r; }g[100001]; double ma[101][101]; int n; double SUM(int i,int j) { double ju; ju=sqrt((g[i].x-g[j].x)*(g[i].x-g[j].x)+(g[i].y-g[j].y)*(g[i].y-g[j].y)+(g[i].z-g[j].z)*(g[i].z-g[j].z)); ju = ju - g[i].r - g[j].r; if(ju>=0) return ju; return 0; } double sum; double dis[101],mi; int pos; bool vis[101]; void prim() { sum=0; for(int i=0;i<n;i++) { dis[i]=ma[0][i]; } vis[0]=1; for(int i=0;i<n;i++) { pos = 0,mi=INF; for(int j=0;j<n;j++) { if(!vis[j] && mi>dis[j]) { mi=dis[j]; pos=j; } } if(mi==INF) return; sum +=mi; vis[pos]=1; for(int j=0;j<n;j++) { if(dis[j]>ma[pos][j]) { dis[j]=ma[pos][j]; } } } } int main() { int i,j; while(scanf("%d",&n)&&n) { memset(ma,0,sizeof(ma)); memset(vis,0,sizeof(vis)); for(i=0;i<n;i++) scanf("%lf%lf%lf%lf",&g[i].x,&g[i].y,&g[i].z,&g[i].r); for(i=0;i<n;i++) { for(j=0;j<n;j++) { if(i!=j) { ma[i][j]=SUM(i,j); } } } sum = 0; prim(); printf("%.3lf ",sum); } return 0; }