#include <iostream>
#include <cmath>
#include <map>
#include <vector>
#include <algorithm>

using namespace std;

double getdist(double x1, double y1, double x2, double y2) {
    return sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
}

typedef pair<double, double> PII;

map<PII, PII> p;
map<PII, int> h;

struct Edge {
    PII p1;
    PII p2;
    double w;
    Edge (PII x, PII y, double z): p1(x), p2(y), w(z) {};
    bool operator < (const Edge& e) const {
        return w < e.w;
    }

};

PII find(PII point) {
    if (point != p[point])p[point] = find(p[point]);
    return p[point];
}

void punion(PII a, PII b) {
    PII x = find(a);
    PII y = find(b);
    if (x != y) {
        if (h[x] > h[y]) {
            p[y] = x;
        } else if (h[x] < h[y]) {
            p[x] = y;
        } else {
            p[x] = y;
            h[y]++;
        }
    }
    return ;
}

double kruskal(vector<Edge> edges){
    double ans=0;
    for(int i=0;i<edges.size();i++){
        PII x = edges[i].p1;
        PII y = edges[i].p2;
        if(find(x)!=find(y)){
            ans+=edges[i].w;
            punion(x, y);
        }
    }

    return ans;
}

int main() {
    int n;
    cin >> n;
    vector<PII> points;
    vector<Edge> edges;

    while (n--) {
        double x, y;
        cin >> x >> y;
        if (p.find({x, y}) == p.end()) {
            h.insert({{x, y}, 0});
            p.insert({{x, y}, {x, y}}); //初始化并查集
        }
        points.push_back({x, y});
    }
    n = points.size();
    //cout<<points.size()<<endl;
    for (int i = 0; i < n - 1; i++) {
        PII p1 = points[i];
        for (int j = i + 1; j < n; j++) {
            PII p2 = points[j];
            double w = getdist(p1.first, p1.second, p2.first, p2.second);
            edges.push_back(Edge(p1, p2, w));
        }
    }
    sort(edges.begin(), edges.end());
    //cout<<edges.size()<<endl;
    double ans = kruskal(edges);
   printf("%.2lf",ans);
    return 0;
}