#include #include #include #include #include #include using namespace std; struct SparseMatrix { vector > a; // [row] vector > nonzero_cols, nonzero_rows; int R, C; SparseMatrix(int R, int C) : R(R), C(C) { a.resize(R); nonzero_cols.resize(R); nonzero_rows.resize(C); } double get(int r, int c) { return a[r].count(c) ? a[r][c] : 0; } void set(int r, int c, double x) { if (x == 0) { a[r].erase(c); nonzero_cols[r].erase(c); nonzero_rows[c].erase(r); } else { a[r][c] = x; nonzero_cols[r].insert(c); nonzero_rows[c].insert(r); } } void sub(int r, int c, double x) { set(r, c, get(r, c) - x); } void div(int r, int c, double x) { set(r, c, get(r, c) / x); } }; #define foreach_const(t, c, i) for(t::const_iterator i = (c).begin(); i != (c).end(); i++) void pivot(SparseMatrix &m, int p, int q) { const double pivot = m.get(p, q); const set nonzero_cols(m.nonzero_cols[p]), nonzero_rows(m.nonzero_rows[q]); foreach_const (set, nonzero_cols, c) m.div(p, *c, pivot); foreach_const (set, nonzero_rows, r) { if (*r != p) { const double k = m.get(*r, q); m.set(*r, q, 0); foreach_const (set, nonzero_cols, c) if (*c != q) m.sub(*r, *c, m.get(p, *c) * k); } } } void simplex(SparseMatrix &m) { int loop = 0; while (true) { int q = -1; const set nonzero_cols(m.nonzero_cols[0]); foreach_const (set, nonzero_cols, c) if (m.get(0, *c) < 0) { q = *c; break; } if (q == -1) break; int p = -1; const set nonzero_rows(m.nonzero_rows[q]); foreach_const (set, nonzero_rows, r) if (m.get(*r, q) > 0 && (p == -1 || m.get(*r, m.C-1) / m.get(*r, q) < m.get(p, m.C-1) / m.get(p, q))) p = *r; if (p == -1) break; pivot(m, p, q); } } typedef complex V2; vector solve(const vector &c) { const int N = c.size(); if (N <= 3) return vector(N, 9999); const int E = N*(N-1)/2; const int V = N+N+E; // (radii) + (surplus) + (slack) SparseMatrix m(1+E, V+1); { // (objective function) + E, V + (constant term) vector r_max(N, 9999); for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) if (j != i && abs(j-i) != 1 && abs(j-i) != N-1) r_max[i] = min(r_max[i], abs(c[i] - c[j])); int cnt_equations = 0, cnt_neighbors = 0; for (int i = 0; i < N; i++) { for (int j = i+1; j < N; j++) { bool should_intersect = (j-i == 1 || j-i == N-1); if (!should_intersect && r_max[i] + r_max[j] <= abs(c[i] - c[j])) continue; m.set(1+cnt_equations, i, 1); m.set(1+cnt_equations, j, 1); if (should_intersect) { m.set(1+cnt_equations, N+cnt_neighbors, -1); // surplus cnt_neighbors++; } m.set(1+cnt_equations, 2*N+cnt_equations, 1); // slack m.set(1+cnt_equations, V, abs(c[i] - c[j])); cnt_equations++; } m.set(0, i, -2); m.set(0, N+i, 1); } } simplex(m); vector r(N, 0); for (int i = 0; i < N; i++) if (m.nonzero_rows[i].size() == 1) r[i] = m.get(*m.nonzero_rows[i].begin(), V); return r; } int main() { for (int N; cin >> N, N; ) { vector c(N); for (int i = 0; i < N; i++) { double x, y; cin >> x >> y; c[i] = V2(x, y); } static bool first = true; if (first) first = false; else printf("\n"); vector r = solve(c); for (int i = 0; i < N; i++) printf("%.10f\n", r[i]); } return 0; }