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

class MainClass
{
    static void Main()
    {
        int N = int.Parse(Console.ReadLine());
        var nxy = new long[N][];
        for (int i = 0; i < N; i++)
        {
            var r = Console.ReadLine().Split().Select(long.Parse).ToArray();
            nxy[i] = new long[3] { i, r[0], r[1] };
        }
        var G = new Graph<(int, long)>(N);
        
        Array.Sort(nxy, (a, b) => a[1].CompareTo(b[1]));
        for (int i = 0; i < N-1; i++)
        {
            int u = (int)nxy[i][0];
            int v = (int)nxy[i + 1][0];
            long cost = Math.Abs(nxy[i][1] - nxy[i + 1][1]);
            G.Add(u, (v, cost));
            G.Add(v, (u, cost));
        }
        Array.Sort(nxy, (a, b) => a[2].CompareTo(b[2]));
        for (int i = 0; i < N - 1; i++)
        {
            int u = (int)nxy[i][0];
            int v = (int)nxy[i + 1][0];
            long cost = Math.Abs(nxy[i][2] - nxy[i + 1][2]);
            G.Add(u, (v, cost));
            G.Add(v, (u, cost));
        }
        MinimumSpanningTree Mtree = new MinimumSpanningTree(G);
        Console.WriteLine(Mtree.costsum);
    }
}
class Graph<T>
{
    private List<T>[] G;
    public Graph(int size)
    {
        G = new List<T>[size];
        for (int i = 0; i < size; i++)
        {
            G[i] = new List<T>();
        }
    }

    public List<T> this[int i] => G[i];
    public void Add(int from, T to) => G[from].Add(to);
    public List<T>[] ToListArray() => G;
    public int Length => G.Length;
}
public class Union_Find
{
    private int[] data;
    public Union_Find(int size)
    {
        data = new int[size];
        for (int i = 0; i < size; i++) data[i] = -1;
    }
    public bool Unite(int x, int y)
    {
        x = Root(x);
        y = Root(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) => Root(x) == Root(y);
    public int Root(int x) => data[x] < 0 ? x : data[x] = Root(data[x]);
    public int getMem(int x) => -data[Root(x)];
}
class MinimumSpanningTree
{
    private Graph<(int to, long cost)> MSTree;
    private List<(int u, int v, long cost)> es;
    private int V;
    public long costsum = 0;
    public MinimumSpanningTree(Graph<(int to, long cost)> G)
    {
        es = new List<(int u, int v, long cost)>();
        MSTree = new Graph<(int to, long cost)>(G.Length);
        for (int i = 0; i < G.Length; i++)
        {
            foreach (var j in G[i])
            {
                es.Add((i, j.to, j.cost));
            }
        }
        V = G.Length;
        costsum = kruskal();
    }

    private long kruskal()
    {
        es.Sort((x, y) => x.cost.CompareTo(y.cost));
        var union = new Union_Find(V);
        long res = 0;
        for (int i = 0; i < es.Count; i++)
        {
            var e = es[i];
            if (!union.IsSameGroup(e.u, e.v))
            {
                union.Unite(e.u, e.v);
                res += e.cost;
                MSTree.Add(e.u, (e.v, e.cost));
                MSTree.Add(e.v, (e.u, e.cost));
            }
        }
        return res;
    }

    public List<(int to, long cost)> this[int i] => MSTree[i];
}

Measured memory_bytes: 69972