#include <bits/stdc++.h>
using namespace std;
struct MCMF {
  struct Edge {
    int to, ri;
    long long cap;
    double cost;
  };
  int n;
  vector<vector<Edge>> graph;
  vector<int> pv, pe;
  vector<double> dist;
  vector<bool> inq;
  void init(int sz) {
    n = sz;
    graph.resize(n);
    pv.resize(n), pe.resize(n);
    dist.resize(n), inq.resize(n);
  }
  void addEdge(int s, int e, long long cap, double cost) {
    Edge forward = {e, (int)graph[e].size(), cap, cost};
    Edge reverse = {s, (int)graph[s].size(), 0, -cost};
    graph[s].push_back(forward);
    graph[e].push_back(reverse);
  }
  bool spfa(int source, int sink, long long &totalFlow, double &totalCost) {
    fill(dist.begin(), dist.end(), 1.0E+9);
    fill(inq.begin(), inq.end(), false);
    priority_queue<pair<double, int>> que;
    que.push({0, source});
    dist[source] = 0;
    while (!que.empty()) {
      double s = que.top().first;
      int v = que.top().second;
      que.pop();
      if (inq[v]) continue;
      inq[v] = true;
      for (int i = 0; i < (int)graph[v].size(); i++) {
        Edge &e = graph[v][i];
        if (e.cap > 0 && dist[e.to] > dist[v] + e.cost) {
          dist[e.to] = dist[v] + e.cost;
          pv[e.to] = v, pe[e.to] = i;
          que.push({-dist[e.to], e.to});
        }
      }
    }
    if (!inq[sink]) {
      return false;
    }
    long long blockFlow = 1LL << 29;
    for (int v = sink; v != source; v = pv[v])
      blockFlow = min(blockFlow, graph[pv[v]][pe[v]].cap);
    for (int v = sink; v != source; v = pv[v]) {
      int ri = graph[pv[v]][pe[v]].ri;
      graph[pv[v]][pe[v]].cap -= blockFlow;
      graph[v][ri].cap += blockFlow;
    }
    totalFlow += blockFlow;
    totalCost += (double)blockFlow * dist[sink];
    return true;
  }
  pair<long long, double> solve(int source, int sink) {
    long long totalFlow = 0;
    double totalCost = 0.0;
    while (spfa(source, sink, totalFlow, totalCost))
      ;
    return make_pair(totalFlow, totalCost);
  }
};
int V, E;
int cap[400000];
double cost[400000], dist[900], pot[900];
int to[400000], pre[400000], last[900], path[900];
bool used[900];
priority_queue<pair<double, int>> q;
class MinCostFlow {
 public:
  MinCostFlow(int n) {
    int i;
    V = n;
    E = 0;
    for ((i) = 0; (i) < (int)(V); (i)++) last[i] = -1;
  }
  void add_edge(int x, int y, int w, double c) {
    cap[E] = w;
    cost[E] = c;
    to[E] = y;
    pre[E] = last[x];
    last[x] = E;
    E++;
    cap[E] = 0;
    cost[E] = -c;
    to[E] = x;
    pre[E] = last[y];
    last[y] = E;
    E++;
  }
  pair<int, double> search(int s, int t) {
    int ansf = 0;
    double ansc = 0;
    int i;
    for ((i) = 0; (i) < (int)(V); (i)++) used[i] = false;
    for ((i) = 0; (i) < (int)(V); (i)++) dist[i] = 1.0E+9;
    dist[s] = 0;
    path[s] = -1;
    q.push(make_pair(0, s));
    while (!q.empty()) {
      int x = q.top().second;
      q.pop();
      if (used[x]) continue;
      used[x] = true;
      for (int e = last[x]; e >= 0; e = pre[e])
        if (cap[e] > 0) {
          double tmp = dist[x] + cost[e] + pot[x] - pot[to[e]];
          if (tmp < dist[to[e]] && !used[to[e]]) {
            dist[to[e]] = tmp;
            path[to[e]] = e;
            q.push(make_pair(-dist[to[e]], to[e]));
          }
        }
    }
    for ((i) = 0; (i) < (int)(V); (i)++) pot[i] += dist[i];
    if (used[t]) {
      ansf = (1 << 29);
      for (int e = path[t]; e >= 0; e = path[to[e ^ 1]])
        ansf = min(ansf, cap[e]);
      for (int e = path[t]; e >= 0; e = path[to[e ^ 1]]) {
        ansc += cost[e] * ansf;
        cap[e] -= ansf;
        cap[e ^ 1] += ansf;
      }
    }
    return make_pair(ansf, ansc);
  }
  pair<int, double> mincostflow(int s, int t) {
    int ansf = 0;
    double ansc = 0;
    int i;
    while (1) {
      pair<int, double> p = search(s, t);
      if (!used[t]) break;
      ansf += p.first;
      ansc += p.second;
    }
    return make_pair(ansf, ansc);
  }
};
int N;
vector<pair<int, int>> li;
int main() {
  scanf("%d", &N);
  li.resize(N);
  for (int i = 0; i < N; i++) {
    scanf("%d%d", &li[i].first, &li[i].second);
  }
  MinCostFlow MC(900);
  for (int i = 0; i < N; i++) {
    for (int j = 0; j < N; j++) {
      if (li[i].second < li[j].second)
        MC.add_edge(i + 3, j + N + 3, 1,
                    sqrt((double)((li[j].second - li[i].second) *
                                  (li[j].second - li[i].second)) +
                         (double)((li[j].first - li[i].first) *
                                  (li[j].first - li[i].first))));
    }
  }
  int ymax = -10000, cnt = 0, root = -1;
  for (int i = 0; i < N; i++) {
    ymax = max(ymax, li[i].second);
  }
  for (int i = 0; i < N; i++) {
    if (li[i].second == ymax) cnt++;
  }
  if (cnt != 1) {
    printf("-1\n");
    return 0;
  }
  for (int i = 0; i < N; i++) {
    if (li[i].second == ymax) root = i;
  }
  for (int i = 0; i < N; i++) {
    if (i != root) MC.add_edge(1, i + 3, 1, 0);
  }
  for (int i = 0; i < N; i++) {
    MC.add_edge(N + i + 3, 2, 2, 0);
  }
  auto ans = MC.mincostflow(1, 2);
  if (ans.first != N - 1)
    printf("-1\n");
  else
    printf("%.9lf\n", ans.second);
}
