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\n" , res); 73 } 74 }
kruskal:就是把边从小到大排序一下,用并查集判断祖节点是否相同,不同就合并。