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

namespace ConsoleApp15
{
    class Class174
    {
        struct edge { public long to, cost; }
        static void Main()
        {
            int N = int.Parse(Console.ReadLine());
            List<Tuple<int, long>> x = new List<Tuple<int, long>>(N);
            List<Tuple<int, long>> y = new List<Tuple<int, long>>(N);
            for(int i = 0; i < N; i++)
            {
                var r = Console.ReadLine().Split().Select(long.Parse).ToArray();
                x.Add(Tuple.Create(i, r[0]));
                y.Add(Tuple.Create(i, r[1]));
            }
            x = x.OrderBy(a => a.Item2).ToList();
            y = y.OrderBy(a => a.Item2).ToList();

            var G = new List<edge>[N];
            for (int i = 0; i < N; i++) G[i] = new List<edge>();
            for(int i = 0; i < N-1; i++)
            {
                G[x[i].Item1].Add(new edge { to = x[i + 1].Item1, cost = Math.Abs(x[i].Item2 - x[i + 1].Item2) });
                G[x[i + 1].Item1].Add(new edge { to = x[i].Item1, cost = Math.Abs(x[i].Item2 - x[i + 1].Item2) });

                G[y[i].Item1].Add(new edge { to = y[i + 1].Item1, cost = Math.Abs(y[i].Item2 - y[i + 1].Item2) });
                G[y[i + 1].Item1].Add(new edge { to = y[i].Item1, cost = Math.Abs(y[i].Item2 - y[i + 1].Item2) });
            }
            long[] d = Enumerable.Repeat(100000000000, N).ToArray();
            d[0] = 0;
            bool[] used = new bool[N];
            used[0] = true;
            var que = new PriorityQueue<Tuple<long, long>>(3 * N, (a,b)=>a.Item1.CompareTo(b.Item1 ));
            que.Push(Tuple.Create(0L, 0L));
            
            while (que.Size > 0)
            {
                var p = que.Pop();
                var v = p.Item2;
                if (d[v] < p.Item1) continue;
                
                used[v] = true;
                for(int i = 0; i < G[v].Count; i++)
                {
                    var e = G[v][i];
                    if(d[e.to]>e.cost&&!used[e.to])
                    {
                        d[e.to] = e.cost;
                        que.Push(Tuple.Create(d[e.to], e.to));
                    }
                }
            }
            
            Console.WriteLine(d.Sum());
        }
    }
    public class PriorityQueue<T>
    {
        public long Size { get; private set; } = 0;
        public long MaxSize { get; private set; } = 0;
        private T[] m_heap;
        private Comparison<T> Comp = null;

        public PriorityQueue(long maxSize, Comparison<T> comp)
        {
            if (maxSize <= 0)
                throw new Exception();
            MaxSize = maxSize;
            m_heap = new T[maxSize];

            Comp = comp;
        }

        public void Push(T x)
        {
            if (Size == MaxSize)
            {
                T[] new_heap = new T[MaxSize << 1];
                Array.Copy(m_heap, new_heap, MaxSize);
                m_heap = new_heap;
                MaxSize <<= 1;
            }

            long i = Size++;
            while (i > 0)
            {
                long p = (i - 1) / 2;
                if (Comp(m_heap[p], x) <= 0)
                    break;
                m_heap[i] = m_heap[p];
                i = p;
            }
            m_heap[i] = x;
        }

        public T Pop()
        {
            if (Size == 0)
                throw new Exception("Queue is empty.");

            T result = m_heap[0];
            T x = m_heap[--Size];
            long i = 0;
            while (i * 2 + 1 < Size)
            {
                long c1 = i * 2 + 1, c2 = i * 2 + 2;
                if (c2 < Size && Comp(m_heap[c2], m_heap[c1]) < 0)
                    c1 = c2;
                if (Comp(m_heap[c1], x) >= 0)
                    break;
                m_heap[i] = m_heap[c1];
                i = c1;
            }
            m_heap[i] = x;

            return result;
        }
    }
}


Measured memory_bytes: 51956