#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;
}