using static System.Math;using static System.Console;using System.Collections.Generic;using System.Linq;using System;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.ComponentModel;

class Program
{
    #region Reader
    static string ReadStr => Console.ReadLine();
    static string[] ReadStrs => Console.ReadLine().Split(' ');
    static int ReadInt => Convert.ToInt32(Console.ReadLine());
    static int[] ReadInts => Console.ReadLine().Split(' ').Select(s => Convert.ToInt32(s)).ToArray();
    static long ReadLong => Convert.ToInt64(Console.ReadLine());
    static long[] ReadLongs => Console.ReadLine().Split(' ').Select(s => Convert.ToInt64(s)).ToArray();
    #endregion

    static int mod = (int)Pow(10, 9) + 7;
    public static int Mod(int a,int mod) { return a % mod >= 0 ? a % mod : a % mod + mod; }
    public static long Mod(long a, int mod) { return a % mod >= 0 ? a % mod : a % mod + mod; }


    public class UnionFind
    {
        public UnionFind(int number)
        {
            Data = new List<int>();
            for (int i = 0; i < number; i++) Data.Add(-1);
        }

        /// <summary>
        /// 負なら親(絶対値はサイズ)　正なら子(絶対値は親のID)
        /// </summary>
        public List<int> Data { get; }

        public int Find(int node)
        {
            //自身が親なら、そのまま返す
            if (Data[node] < 0) return node;

            //子なら、その親を呼び、さらにその親を探す。再帰的に呼び出しrootを見つけ、全ての子の親をrootにする
            return Data[node] = Find(Data[node]);
        }

        public bool Unite(int node1, int node2)
        {
            //二つの点の親をさがす
            node1 = Find(node1);
            node2 = Find(node2);

            //二つの親が一致しているなら、することはない
            if (node1 == node2) return false;

            int parent = 0;
            int newSon = 0;

            //サイズが小さいほうが、大きい方の子になる(親のDataの値は負であることに注意)
            if (Data[node1] > Data[node2])
            {
                parent = node2;
                newSon = node1;
            }
            else
            {
                parent = node1;
                newSon = node2;
            }

            Data[parent] += Data[newSon];
            Data[newSon] = parent;

            return true;
        }
    }


    static void Main()
    {
        int N = ReadInt;

        (int X, int Y,int index)[] XYs = new (int x, int y,int index)[N];

        for (int i = 0; i < N; i++)
        {
            int[] v = ReadInts;
            XYs[i] = (v[0], v[1],i);
        }

        Array.Sort(XYs, (n, m) => (n.X - m.X));

        List<(int city1, int city2, int cost)> roads = new List<(int city1, int city2, int cost)>();

        for (int i = 1; i < N; i++)
        {
            roads.Add((XYs[i - 1].index, XYs[i].index, XYs[i].X - XYs[i - 1].X));
        }

        Array.Sort(XYs, (n, m) => (n.Y - m.Y));

        for (int i = 1; i < N; i++)
        {
            roads.Add((XYs[i - 1].index, XYs[i].index, XYs[i].Y - XYs[i - 1].Y));
        }

        UnionFind tree = new UnionFind(N);
        int count = 0;
        long cost = 0;
       roads.Sort((r1, r2) => r1.cost - r2.cost);
        foreach (var road in roads)
        {
            if (tree.Find(road.city1) != tree.Find(road.city2))
            {
                tree.Unite(road.city1, road.city2);
                count++;
            //    WriteLine(road.cost);
                cost += road.cost;
                if (count == N - 1) break;
            }
        }
        WriteLine(cost);
    }







}


Measured memory_bytes: 55808