using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

public class Contest
{
	public static void Main()
	{
        int n;
		VT<int,int>[] xyl;
		MyIO.ReadMulti(out n);
		MyIO.ReadLines(n, out xyl);
 
		VT<int,int,int>[] xsl = new VT<int, int, int>[n];
		VT<int,int,int>[] ysl = new VT<int, int, int>[n];
		for(int i=0;i<n;i++) {
			xsl[i] = new VT<int, int, int>(xyl[i].Item1,xyl[i].Item2,i);
			ysl[i] = new VT<int, int, int>(xyl[i].Item1,xyl[i].Item2,i);
		}
		Array.Sort(xsl, (x,y)=>x.Item1-y.Item1);
		Array.Sort(ysl, (x,y)=>x.Item2-y.Item2);

		Dictionary<long,int> sl = new Dictionary<long, int>(10*n); 
		for(int i=0;i<n-1;i++){
			long i1 = (long)Math.Min(xsl[i].Item3,xsl[i+1].Item3) * (long)n + (long)Math.Max(xsl[i].Item3,xsl[i+1].Item3) ;
			int c1 = Math.Min( Math.Abs(xsl[i].Item1-xsl[i+1].Item1), Math.Abs(xsl[i].Item2-xsl[i+1].Item2) );
			if(sl.ContainsKey(i1)){
				if(c1<sl[i1]) sl[i1] = c1;
			}else{
				sl[i1] = c1;
			}
			long i2 = (long)Math.Min(ysl[i].Item3,ysl[i+1].Item3) * (long)n + (long)Math.Max(ysl[i].Item3,ysl[i+1].Item3) ;
			int c2 = Math.Min( Math.Abs(ysl[i].Item1-ysl[i+1].Item1), Math.Abs(ysl[i].Item2-ysl[i+1].Item2) );
			if(sl.ContainsKey(i2)){
				if(c2<sl[i2]) sl[i2] = c2;
			}else{
				sl[i2] = c2;
			}
		}

		List<VT<int,int,int>> g = new List<VT<int, int, int>>();
		foreach(var s in sl){
			int k = (int)(s.Key / n);
			int l = (int)(s.Key % n);
			g.Add(new VT<int, int, int>(k,l,s.Value));
		}

		VT<int,int,int>[] o;
		long r = Kruskal(g.ToArray(), n, out o);
 
		MyIO.WriteMulti(r);

	}




	public static long Kruskal(VT<int,int,int>[] inEdges, int V, out VT<int,int,int>[] outEdges) {
		Array.Sort(inEdges, (x,y)=>(x.Item3.CompareTo(y.Item3)));
		UnionFind tree = new UnionFind(V);
		long ret = 0;
		List<VT<int,int,int>> oedge = new List<VT<int, int, int>>();
		foreach(var e in inEdges) {
			if(tree.Unite(e.Item1, e.Item2)) {
				ret += e.Item3;
				oedge.Add(e);
			}
		}
		outEdges = oedge.ToArray();
		return ret;
	}

}


public class UnionFind {
    private int[] data;

    public UnionFind(int size) {
        data = new int[size];
        for (int i = 0; i < size; i++) data[i] = -1;
    }

    public bool Unite(int x, int y) {
        x = Find(x);
        y = Find(y);

        if (x != y) {
            if (data[y] < data[x]) {
                var tmp = y;
                y = x;
                x = tmp;
            }
            data[x] += data[y];
            data[y] = x;
        }
        return x != y;
    }

    public bool IsSameGroup(int x, int y) { return Find(x) == Find(y); }

    public int Find(int x) { return data[x] < 0 ? x : data[x] = Find(data[x]); }

    public int Size(int x) { return -data[Find(x)]; }

}



public struct VT<T, U>
{
	public T Item1; public U Item2;
    public VT(T a, U b) { Item1 = a; Item2 = b; }
}
public struct VT<T, U, V>
{
	public T Item1; public U Item2; public V Item3;
    public VT(T a, U b, V c) { Item1 = a; Item2 = b; Item3 = c; }
}
public struct VT<T, U, V, W>
{
	public T Item1; public U Item2; public V Item3; public W Item4;
    public VT(T a, U b, V c, W d) { Item1 = a; Item2 = b; Item3 = c; Item4 = d; }
}

public class Printer : System.IO.StreamWriter
{
	public override IFormatProvider FormatProvider { get { return System.Globalization.CultureInfo.InvariantCulture; } }
	public Printer(System.IO.Stream stream) : base(stream, new UTF8Encoding(false, true)) { }
	public Printer(System.IO.Stream stream, Encoding encoding) : base(stream, encoding) { }
}
public static class MyIO
{
	private static char[] splitter = new char[] {' '};
	private static bool eq<T, U>() => typeof(T).Equals(typeof(U));
	private static T ct<T, U>(U a) => (T)Convert.ChangeType(a, typeof(T));
	private static T cv<T>(string s) => eq<T, int>()    ? ct<T, int>(int.Parse(s))
	                                  : eq<T, long>()   ? ct<T, long>(long.Parse(s))
	                                  : eq<T, double>() ? ct<T, double>(double.Parse(s, System.Globalization.CultureInfo.InvariantCulture))
	                                  : eq<T, char>()   ? ct<T, char>(s[0])
	                                                    : ct<T, string>(s);				
	public static string[] ReadMulti<T>(out T a) {
		var ar = Console.ReadLine().Split(splitter, StringSplitOptions.RemoveEmptyEntries); 
		a = cv<T>(ar[0]);
		return ar;
	}
	public static string[] ReadMulti<T, U>(out T a, out U b) {
		var ar = ReadMulti<T>(out a); 
        b = cv<U>(ar[1]);
		return ar;
	}
	public static string[] ReadMulti<T, U, V>(out T a, out U b, out V c) {
		var ar = ReadMulti<T, U>(out a, out b); 
        c = cv<V>(ar[2]);
		return ar;
	}
	public static string[] ReadMulti<T, U, V, W>(out T a, out U b, out V c, out W d) {
		var ar = ReadMulti<T, U, V>(out a, out b, out c); 
        d = cv<W>(ar[3]);
		return ar;
	}
	public static string[] ReadMulti<T, U, V, W, X>(out T a, out U b, out V c, out W d, out X e) {
		var ar = ReadMulti<T, U, V, W>(out a, out b, out c, out d); 
        e = cv<X>(ar[4]);
		return ar;
	}
	public static string[] ReadMulti<T, U, V, W, X, Y>(out T a, out U b, out V c, out W d, out X e, out Y f) {
		var ar = ReadMulti<T, U, V, W, X>(out a, out b, out c, out d, out e); 
        f = cv<Y>(ar[5]);
		return ar;
	}
	public static string[] ReadArray<T>(out T[] a) {		
		var ar = Console.ReadLine().Split(splitter, StringSplitOptions.RemoveEmptyEntries);
		a = ar.Select(cv<T>).ToArray();
		return ar;
	}		
	public static string[][] ReadLines<T>(int n, out T[] a) {
		a = new T[n];
		string[][] arr = new string[n][];
		for(int i=0; i<n; i++) arr[i] = ReadMulti(out a[i]);
		return arr;
	}
	public static string[][] ReadLines<T, U>(int n, out VT<T, U>[] a) {
		a = new VT<T, U>[n];
		string[][] arr = new string[n][];
		for(int i=0; i<n; i++) {
			T o; U p;
			arr[i] = ReadMulti(out o, out p);
			a[i] = new VT<T, U>(o, p);
		}
		return arr;
	}
	public static string[][] ReadLines<T, U, V>(int n, out VT<T, U, V>[] a) {
		a = new VT<T, U, V>[n];
		string[][] arr = new string[n][];
		for(int i=0; i<n; i++) {
			T o; U p; V q;
			arr[i] = ReadMulti(out o, out p, out q);
			a[i] = new VT<T, U, V>(o, p, q);
		}
		return arr;
	}
	public static string[][] ReadLines<T, U, V, W>(int n, out VT<T, U, V, W>[] a) {
		a = new VT<T, U, V, W>[n];
		string[][] arr = new string[n][];
		for(int i=0; i<n; i++) {
			T o; U p; V q; W r;
			arr[i] = ReadMulti(out o, out p, out q, out r);
			a[i] = new VT<T, U, V, W>(o, p, q, r);
		}
		return arr;
	}
	public static string[][] ReadMatrix<T>(int n, out T[][] a) {
		a = new T[n][];
		string[][] arr = new string[n][];
		for(int i=0; i<n; i++) arr[i] = ReadArray(out a[i]);
		return arr;
	}

	private static void wwp(Action act){
		var sw = new Printer(Console.OpenStandardOutput()){AutoFlush = false};
		Console.SetOut(sw);
		act();
		Console.Out.Flush();
		sw.AutoFlush = true;
		Console.SetOut(sw);
	}
	public static void WriteMulti(params object[] a) {
		wwp(()=>{
			foreach(object x in a) Console.Write("{0} ", x);
			Console.WriteLine();
		});
	}
	public static void WriteArray<T>(T[] a) {
		wwp(()=>{
			foreach(T x in a) Console.Write("{0} ", x);
			Console.WriteLine();
		});
	}
	public static void WriteLines<T>(T[] a) {
		wwp(()=>{
			foreach(T x in a) Console.WriteLine(x);
		});
	}



}





Measured memory_bytes: 57008