AOJ1127 Building a Space Station
問題リンク Building a Space Station
- 概要
N個の球状のスペースステーションの3次元座標(x,y,z)と半径rが与えられる。
あるスペースステーションから全てのスペースステーションに移動できるように橋を架けるとき、架ける橋の長さの合計を最小にせよ。
スペースステーションiからjへ移動できる条件は、橋をかけたか、iとjに共通部分がある場合をいう。
N < 100
0 < x, y, z, r < 100.0
- 解法
ストレートに最小全域木の問題になります。橋を架ける前に、既に接触している球同士はくっつけてしまってから、クラスカル法なりプリム法なりで最小全域木を作って行きます。
- ソース
import java.util.Arrays; import java.util.PriorityQueue; import java.util.Scanner; //Building a Space Station public class AOJ1127 { class E implements Comparable<E>{ int s, t; double d; public E(int s, int t, double d) { this.s = s; this.t = t; this.d = d; } public int compareTo(E o) { return d-o.d<0?-1:o.d-d<0?1:0; } } void run(){ Scanner sc = new Scanner(System.in); for(;;){ int n = sc.nextInt(); if(n==0)break; UnionFind u = new UnionFind(n); double[][] p = new double[n][3]; double[] r = new double[n]; for(int i=0;i<n;i++){ for(int j=0;j<3;j++)p[i][j]=sc.nextDouble(); r[i] = sc.nextDouble(); } PriorityQueue<E> q = new PriorityQueue<E>(); for(int i=0;i<n;i++)for(int j=i+1;j<n;j++){ if(u.find(i, j))continue; double d = Math.sqrt(Math.pow(p[i][0]-p[j][0], 2)+Math.pow(p[i][1]-p[j][1], 2)+Math.pow(p[i][2]-p[j][2], 2))-r[i]-r[j]; if(d<1e-6)u.union(i, j); else q.add(new E(i, j, d)); } double res = 0; while(u.num>1){ E e = q.poll(); if(!u.find(e.s, e.t)){ u.union(e.s, e.t); res+=e.d; } } System.out.printf("%.3f\n", res); } } class UnionFind { final int[] tree; int num; public UnionFind(int n) { this.tree = new int[n]; Arrays.fill(tree, -1); num=n; } // merge the set contains x and the set contains y void union(int x, int y) { x = root(x); y = root(y); if(x != y) { if(tree[x] < tree[y]) { x ^= y; y ^= x; x^= y; } tree[x] += tree[y]; tree[y] = x; num--; } } // decide if x and y belong to the same set boolean find(int x, int y) { return root(x) == root(y); } int root(int x) { return tree[x] < 0 ? x : (tree[x] = root(tree[x])); } // return size of the set contains x int size(int x) { return -tree[root(x)]; } // return the number of sets int getNum() { return num; } } public static void main(String[] args) { new AOJ1127().run(); } }