// Arup Guha
// 11/11/2012
// Solution to 2012 South East Regional Problem H (both D1 and D2): Tsunami

import java.util.*;

//  Just used for the Disjoint set class.
class pair {
	public int parent;
	public int height;

	public pair(int a, int b) {
		parent = a;
		height = b;
	}
}

// Basic Disjoint Set without path compression.
class dset {

	private pair[] parents;

	public dset(int n) {
		parents = new pair[n];
		for (int i=0; i<n; i++)
			parents[i] = new pair(i,0);
	}

	public int find(int child) {
		while (parents[child].parent != child)
			child = parents[child].parent;
		return child;
	}

	public boolean same(int c1, int c2) {
		int root1 = find(c1);
		int root2 = find(c2);
		return root1 == root2;
	}

	public boolean union(int c1, int c2) {
		int root1 = find(c1);
		int root2 = find(c2);

		// Nothing to union.
		if (root1 == root2)
			return false;

		// Root 1 stays parent.
		if (parents[root1].height > parents[root2].height) {
			parents[root2].parent = root1;
		}

		// Tie case get assigned to root 1 also.
		else if (parents[root1].height == parents[root2].height) {
			parents[root2].parent = root1;
			parents[root1].height++;
		}

		// Must use root 2 here.
		else {
			parents[root1].parent = root2;
		}

		return true;
	}
}

// Stores each possible edge for the minimum spanning tree.
class edge implements Comparable<edge> {

	public int v1;
	public int v2;
	public point p1;
	public point p2;
	public double distance;

	// Here we store both the vertex numbers and the underlying points.
	public edge(int start, int end, point point1, point point2) {
		v1 = start;
		v2 = end;
		p1 = point1;
		p2 = point2;
		distance = p1.getDistance(p2);
	}

	public point getMaxPt() {
		if (p1.compareTo(p2) > 0)
			return p1;
		return p2;
	}

	// Edited compareTo, so we never add any offending edges.
	public int compareTo(edge other) {

		// We want to minimize the y coordinate of either point in the new edge we
		// add to our MST.
		if (this.getMaxPt().compareTo(other.getMaxPt()) > 0)
			return 1;
		else if (this.getMaxPt().compareTo(other.getMaxPt()) < 0)
			return -1;

		// Once we've done that, we just want to minimize our distance, as usual.
		if (this.distance < other.distance)
			return -1;
		else if (this.distance > other.distance)
			return 1;
		return 0;
	}
}

// Stores a Cartesian point.
class point implements Comparable<point> {
	public int x;
	public int y;

	public point(int myx, int myy) {
		x = myx;
		y = myy;
	}

	public double getDistance(point p) {
		return Math.sqrt((x-p.x)*(x-p.x) + (y-p.y)*(y-p.y));
	}

	public int compareTo(point other) {
		if (y != other.y)
			return this.y - other.y;
		return 0;
	}
}

public class h {

	public static void main(String[] args) {

		Scanner stdin = new Scanner(System.in);

		int n = stdin.nextInt();

		// Go through each case.
		while (n != 0) {

			// Read in raw data.
			point[] cities = new point[n];
			for (int i=0; i<n; i++) {
				int x = stdin.nextInt();
				int y = stdin.nextInt();
				cities[i] = new point(x,y);
			}

			edge[] list = new edge[n*(n-1)/2];
			int index = 0;
			for (int i=0; i<n; i++) {
				for (int j=i+1; j<n; j++) {
					list[index] = new edge(i, j, cities[i], cities[j]);
					index++;
				}
			}

			Arrays.sort(list);

			// Output the answer for this case.
			System.out.printf("%.2f\n",mst(list, n));

			// Go to the next case.
			n = stdin.nextInt();
		}
	}

	// Return the length of the sum of the edges in the mst of the graph
	// of n vertices represented in allEdges.
	public static double mst(edge[] list, int n) {

		dset mydset = new dset(n);
		double answer = 0;

		int numedges = 0;
		int index = 0;

		// Keep on going until we get the right number of edges.
		while (numedges < n-1) {

			edge next = list[index];

			if (mydset.union(next.v1, next.v2)) {
				answer += next.distance;
				numedges++;
			}
			index++;
		}

		return answer;
	}
}