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