#include <iostream>
#include <vector>
#include <queue>
#include <cstring>
#include <cmath>
#include <iomanip>
using namespace std;
const int maxn=100;
int father[maxn];
int height[maxn];
struct point{
    float x;
    float y;
    point(float a,float b):x(a),y(b){};
};
struct edge{
    int from;
    int to;
    float length;
    edge(int a,int b,float c):from(a),to(b),length(c){};
    bool operator< (edge o) const{
        return length>o.length;
    }
};
vector<point> store;
priority_queue<edge> q;
void init(){
    store.clear();
    while(!q.empty()){
    	q.pop();
	}
    memset(height,0,sizeof(height));
    for(int i=0;i<maxn;i++) {
	father[i]=i;
}
}
int findfather(int x){
    if(x!=father[x]) father[x]=findfather(father[x]);
    return father[x];
}
void Union(int x,int y){
    x=findfather(x);
    y=findfather(y);
    if(x==y) return;
    if(height[x]>height[y]) father[y]=x;
    else if(height[x]<height[y]) father[x]=y;
    else {
        father[y]=x;
        height[x]++;
    }
}
bool isOneUnion(int n){
    int nums=0;
    for(int i=0;i<n;i++){
        if(i==father[i]) nums++;
    }
    if(nums==1) return true;
    else return false;
}
float krustal(int n){
    float dist=0;
    while(!isOneUnion(n)){
    edge e=q.top();
    q.pop();
    if(findfather(e.from)==findfather(e.to)) continue;
    else {
        Union(e.from,e.to);
        dist+=e.length;}
    }
    return dist;
}
int main(){
    int n;
    while(cin>>n){
        init();
        int p=n;
        while(p>0){
            float x,y;
            cin>>x>>y;
            store.push_back(point(x,y));
            p--;
        }
        for(int i=0;i<store.size();i++){
            for(int j=i+1;j<store.size();j++){
                float l1=pow(store[i].x-store[j].x,2);
                float l2=pow(store[i].y-store[j].y,2);
                float l=pow(l1+l2,0.5);
                q.push(edge(i,j,l));
            }
        }
        cout<<fixed<<setprecision(2)<<krustal(n)<<endl;
    }
}