POJ 2031 Building a Space Station

题目链接:http://poj.org/problem?id=2031

题目意思是给出三维坐标系上的一些球的球心坐标和其半径,搭建通路,使得他们能够相互连通。如果两个球有重叠的部分则算为已连通,无需再搭桥。求搭建通路的最小费用(费用就是边权,就是两个球面之间的距离)。就是简单的最小生成树。

prim:

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <cmath>
 5 using namespace std;
 6 const int MAXN = 105;
 7 struct data {
 8     double x , y , z , r;
 9 }a[MAXN];
10 double d[MAXN] , cost[MAXN][MAXN] , INF = 1e9;
11 bool vis[MAXN];
12 
13 void init(int n) {
14     for(int i = 0 ; i <= n ; i++) {
15         for(int j = 0 ; j <= n ; j++)
16             cost[i][j] = INF;
17         d[i] = INF;
18         vis[i] = false;
19     }
20 }
21 
22 inline double f(double x , double y) {
23     return (x - y) * (x - y);
24 }
25 
26 double dis(int i , int j) {
27     double temp = f(a[i].x , a[j].x) + f(a[i].y , a[j].y) + f(a[i].z , a[j].z);
28     return sqrt(temp);
29 }
30 
31 double prim(int s , int n) {
32     d[s] = 0;
33     double res = 0;
34     while(1) {
35         int u = -1;
36         double Min = INF;
37         for(int i = 1 ; i <= n ; i++) {
38             if(!vis[i] && Min > d[i]) {
39                 Min = d[i];
40                 u = i;
41             }
42         }
43         if(u == -1)
44             return res;
45         vis[u] = true;
46         res += d[u];
47         for(int i = 1 ; i <= n ; i++) {
48             d[i] = (d[i] > cost[u][i] ? cost[u][i] : d[i]);
49         }
50     }
51 }
52 
53 int main()
54 {
55     int n;
56     ios::sync_with_stdio(false);
57     while(cin >> n && n) {
58         init(n);
59         for(int i = 1 ; i <= n ; i++) {
60             cin >> a[i].x >> a[i].y >> a[i].z >> a[i].r;
61         }
62         for(int i = 1 ; i < n ; i++) {
63             for(int j = i + 1 ; j <= n ; j++) {
64                 double temp = a[i].r + a[j].r , temp2 = dis(i , j);
65                 if(temp >= temp2)
66                     cost[i][j] = cost[j][i] = 0;
67                 else
68                     cost[i][j] = cost[j][i] = temp2 - temp;
69             }
70         }
71         double res = prim(1 , n);
72         printf("%.3f
" , res);
73     }
74 }

kruskal:就是把边从小到大排序一下,用并查集判断祖节点是否相同,不同就合并。

原文地址:https://www.cnblogs.com/Recoder/p/5304040.html