Problem:
Score : 500 points

Problem Statement

There are N towns on a plane. The i-th town is located at the coordinates (x_i,y_i). There may be more than one town at the same coordinates.

You can build a road between two towns at coordinates (a,b) and (c,d) for a cost of min(|a-c|,|b-d|) yen (the currency of Japan). It is not possible to build other types of roads.

Your objective is to build roads so that it will be possible to travel between every pair of towns by traversing roads. At least how much money is necessary to achieve this?

Constraints

2 ≤ N ≤ 10^5

0 ≤ x_i,y_i ≤ 10^9

All input values are integers.

Input

Input is given from Standard Input in the following format:

N
x_1 y_1
x_2 y_2
:
x_N y_N

Output

Print the minimum necessary amount of money in order to build roads so that it will be possible to travel between every pair of towns by traversing roads.

Sample Input 1

3
1 5
3 9
7 8

Sample Output 1

3

Build a road between Towns 1 and 2, and another between Towns 2 and 3. The total cost is 2+1=3 yen.

Sample Input 2

6
8 3
4 9
12 19
18 1
13 5
7 6

Sample Output 2

8

Solution in C# (Mono 4.6.2.0) (judge verdict: Accepted)

using Yorukatsu053.Questions;
using Yorukatsu053.Extensions;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;

namespace Yorukatsu053.Questions
{
    /// <summary>
    /// https://atcoder.jp/contests/arc092/tasks/arc092_a
    /// </summary>
    public class QuestionF : AtCoderQuestionBase
    {
        public override IEnumerable<object> Solve(TextReader inputStream)
        {
            var cityCount = inputStream.ReadInt();
            var xCoordinates = new IndexCoordinatePair[cityCount];
            var yCoordinates = new IndexCoordinatePair[cityCount];

            for (int i = 0; i < xCoordinates.Length; i++)
            {
                var xy = inputStream.ReadIntArray();
                var x = xy[0];
                var y = xy[1];
                xCoordinates[i] = new IndexCoordinatePair(i, x);
                yCoordinates[i] = new IndexCoordinatePair(i, y);
            }

            Array.Sort(xCoordinates);
            Array.Sort(yCoordinates);

            var cityPairs = new List<CityPair>();
            for (int i = 0; i + 1 < cityCount; i++)
            {
                var xDiff = xCoordinates[i + 1].Coordinate - xCoordinates[i].Coordinate;
                var yDiff = yCoordinates[i + 1].Coordinate - yCoordinates[i].Coordinate;
                cityPairs.Add(new CityPair(xCoordinates[i].Index, xCoordinates[i + 1].Index, xDiff));
                cityPairs.Add(new CityPair(yCoordinates[i].Index, yCoordinates[i + 1].Index, yDiff));
            }

            cityPairs.Sort();

            var unionFind = new UnionFindTree(cityCount);
            long totalCost = 0;
            foreach (var cityPair in cityPairs)
            {
                if (!unionFind.IsInSameGroup(cityPair.CityA, cityPair.CityB))
                {
                    totalCost += cityPair.Distance;
                    unionFind.Unite(cityPair.CityA, cityPair.CityB);
                }
            }

            yield return totalCost;
        }

        struct IndexCoordinatePair : IComparable<IndexCoordinatePair>
        {
            public int Index { get; }
            public int Coordinate { get; }

            public IndexCoordinatePair(int index, int coordinate)
            {
                Index = index;
                Coordinate = coordinate;
            }

            public int CompareTo(IndexCoordinatePair other) => Coordinate.CompareTo(other.Coordinate);
        }

        struct CityPair : IComparable<CityPair>
        {
            public int CityA { get; }
            public int CityB { get; }
            public int Distance { get; }

            public CityPair(int cityA, int cityB, int distance)
            {
                CityA = cityA;
                CityB = cityB;
                Distance = distance;
            }

            public int CompareTo(CityPair other) => Distance.CompareTo(other.Distance);
        }

        public class UnionFindTree
        {
            private UnionFindNode[] _nodes;
            public int Count => _nodes.Length;
            public int Groups { get; private set; }

            public UnionFindTree(int count)
            {
                _nodes = Enumerable.Range(0, count).Select(i => new UnionFindNode(i)).ToArray();
                Groups = _nodes.Length;
            }

            public void Unite(int index1, int index2)
            {
                var succeed = _nodes[index1].Unite(_nodes[index2]);
                if (succeed)
                {
                    Groups--;
                }
            }

            public bool IsInSameGroup(int index1, int index2) => _nodes[index1].IsInSameGroup(_nodes[index2]);
            public int GetGroupSizeOf(int index) => _nodes[index].GetGroupSize();

            private class UnionFindNode
            {
                private int _height;        // rootのときのみ有効
                private int _groupSize;     // 同上
                private UnionFindNode _parent;
                public int ID { get; }

                public UnionFindNode(int id)
                {
                    _height = 0;
                    _groupSize = 1;
                    _parent = this;
                    ID = id;
                }

                public UnionFindNode FindRoot()
                {
                    if (_parent != this) // not ref equals
                    {
                        var root = _parent.FindRoot();
                        _parent = root;
                    }

                    return _parent;
                }

                public int GetGroupSize() => FindRoot()._groupSize;

                public bool Unite(UnionFindNode other)
                {
                    var thisRoot = this.FindRoot();
                    var otherRoot = other.FindRoot();

                    if (thisRoot == otherRoot)
                    {
                        return false;
                    }

                    if (thisRoot._height < otherRoot._height)
                    {
                        thisRoot._parent = otherRoot;
                        otherRoot._groupSize += thisRoot._groupSize;
                        otherRoot._height = Math.Max(thisRoot._height + 1, otherRoot._height);
                        return true;
                    }
                    else
                    {
                        otherRoot._parent = thisRoot;
                        thisRoot._groupSize += otherRoot._groupSize;
                        thisRoot._height = Math.Max(otherRoot._height + 1, thisRoot._height);
                        return true;
                    }
                }

                public bool IsInSameGroup(UnionFindNode other) => this.FindRoot() == other.FindRoot();

                public override string ToString() => $"{ID} root:{FindRoot().ID}";
            }
        }
    }
}

namespace Yorukatsu053
{
    class Program
    {
        static void Main(string[] args)
        {
            IAtCoderQuestion question = new QuestionF();    // 問題に合わせて書き換え
            var answers = question.Solve(Console.In);
            foreach (var answer in answers)
            {
                Console.WriteLine(answer);
            }
        }
    }
}

#region Base Classes

namespace Yorukatsu053.Questions
{

    public interface IAtCoderQuestion
    {
        IEnumerable<object> Solve(string input);
        IEnumerable<object> Solve(TextReader inputStream);
    }

    public abstract class AtCoderQuestionBase : IAtCoderQuestion
    {
        public IEnumerable<object> Solve(string input)
        {
            var stream = new MemoryStream(Encoding.Unicode.GetBytes(input));
            var reader = new StreamReader(stream, Encoding.Unicode);

            return Solve(reader);
        }

        public abstract IEnumerable<object> Solve(TextReader inputStream);
    }

}

#endregion

#region Extensions

namespace Yorukatsu053.Extensions
{
    internal static class TextReaderExtensions
    {
        internal static int ReadInt(this TextReader reader) => int.Parse(ReadString(reader));
        internal static long ReadLong(this TextReader reader) => long.Parse(ReadString(reader));
        internal static double ReadDouble(this TextReader reader) => double.Parse(ReadString(reader));
        internal static string ReadString(this TextReader reader) => reader.ReadLine();

        internal static int[] ReadIntArray(this TextReader reader, char separator = ' ') => ReadStringArray(reader, separator).Select(int.Parse).ToArray();
        internal static long[] ReadLongArray(this TextReader reader, char separator = ' ') => ReadStringArray(reader, separator).Select(long.Parse).ToArray();
        internal static double[] ReadDoubleArray(this TextReader reader, char separator = ' ') => ReadStringArray(reader, separator).Select(double.Parse).ToArray();
        internal static string[] ReadStringArray(this TextReader reader, char separator = ' ') => reader.ReadLine().Split(separator);
    }
}

#endregion