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 Java8 (OpenJDK 1.8.0) (judge verdict: Time Limit Exceeded)

import java.io.IOException;
import java.io.InputStream;
import java.util.*;

public class Main {
	
    public static void main(String[] args) {
    	FastScanner sc = new FastScanner();

    	int n = sc.nextInt();
    	
    	ArrayList<Pair> l = new ArrayList<>();
    	
    	for(int i=0;i<n;i++){
    		l.add(new Pair(i,sc.nextInt(),sc.nextInt()));
    	}

    	Kraskal g = new Kraskal(n);
    	
    	Collections.sort(l);
    	
    	for(int i=0;i<n-1;i++){
    		g.addEdge(l.get(i).n,l.get(i+1).n,l.get(i+1).a -l.get(i).a);
    	}
    	
    	Collections.sort(l,new PC2());
    	
    	for(int i=0;i<n-1;i++){
    		g.addEdge(l.get(i).n,l.get(i+1).n,l.get(i+1).b -l.get(i).b);
    	}
    	
    	System.out.println(g.KraskalWeight());
    }
    
}

class Pair implements Comparable<Pair>{
	int a,b;
	int n;
	
	public Pair(int n, int a, int b){
		this.a = a;
		this.b = b;
		this.n = n;
	}
	
	@Override
	public int compareTo(Pair o){
		if(a!=o.a){
			return Integer.compare(a,o.a);
		}
		return Integer.compare(b, o.b);
	}
}

class PC2 implements Comparator<Pair>{
	@Override
	public int compare(Pair o1,Pair o2){
		if(o1.b!=o2.b){
			return Integer.compare(o1.b,o2.b);
		}
		return Integer.compare(o1.a, o2.a);
	}
}

class Kraskal {
	int vnum;
	ArrayList<WEdge2> elist;
	
	public Kraskal(int vnum){
		this.vnum = vnum;
		elist = new ArrayList<>();
	}
	
	void addEdge(int u, int v, int w){
		elist.add(new WEdge2(u,v,w));
	}
	
	//クラスカル法で最小全域木を求める
	ArrayList<WEdge2> KraskalTree(){		
		//UFT
		class UFT{
			int[] par;
			int[] rank;
			
			public UFT(int n){
				par = new int[n];
				rank = new int[n];
				
				for(int i=0;i<n;i++){
					par[i] = i;
				}
			}
			
			//木の根を求める
			public int find(int x){
				if(par[x] == x){
					return x;
				}
				else{
					return par[x] = find(par[x]);
				}
			}
			
			//xとyの属する集合を併合
			void unite(int x, int y){
				int px = find(x);
				int py = find(y);
				
				if(px == py){
					return;
				}
				else if(rank[px] < rank[py]){
					par[px] = py;

				}
				else{
					par[py] = px;
					if(rank[px]==rank[py]){
						rank[px]++;
					}
				}
				
			}
			
			//xとyが同じ集合に属するか
			boolean isEquivalent(int x, int y){
				return find(x) == find(y);
			}
		}
		
		ArrayList<WEdge2> s = elist;
		ArrayList<WEdge2> forest = new ArrayList<>();
		Collections.sort(s);
		UFT uft = new UFT(vnum);
		
		while(!s.isEmpty()){
			WEdge2 now = s.remove(0);
			
			if(!uft.isEquivalent(now.u,now.v)){
				forest.add(now);
				uft.unite(now.u, now.v);
			}
		}
		
		return forest;
	}

	//クラスカル法で最小全域木の重みの和を求める
	long KraskalWeight(){		
		//UFT
		class UFT{
			int[] par;
			int[] rank;
			
			public UFT(int n){
				par = new int[n];
				rank = new int[n];
				
				for(int i=0;i<n;i++){
					par[i] = i;
				}
			}
			
			//木の根を求める
			public int find(int x){
				if(par[x] == x){
					return x;
				}
				else{
					return par[x] = find(par[x]);
				}
			}
			
			//xとyの属する集合を併合
			void unite(int x, int y){
				int px = find(x);
				int py = find(y);
				
				if(px == py){
					return;
				}
				else if(rank[px] < rank[py]){
					par[px] = py;

				}
				else{
					par[py] = px;
					if(rank[px]==rank[py]){
						rank[px]++;
					}
				}
				
			}
			
			//xとyが同じ集合に属するか
			boolean isEquivalent(int x, int y){
				return find(x) == find(y);
			}
		}
		
		ArrayList<WEdge2> s = elist;
		Collections.sort(s);
		UFT uft = new UFT(vnum);
		long sum = 0;
		
		while(!s.isEmpty()){
			WEdge2 now = s.remove(0);
			
			if(!uft.isEquivalent(now.u,now.v)){
				sum += now.w;
				uft.unite(now.u, now.v);
			}
		}
		
		return sum;
	}
	
}

class WEdge2 implements Comparable<WEdge2>{
	int u;
	int v;
	int w;
	
	public WEdge2(int u, int v, int w){
		this.u = u;
		this.v = v;
		this.w = w;
	}
	
	@Override
	public int compareTo(WEdge2 o){
		return Integer.compare(w, o.w);
	}
}

class FastScanner {
    private final InputStream in = System.in;
    private final byte[] buffer = new byte[1024];
    private int ptr = 0;
    private int buflen = 0;
    private boolean hasNextByte() {
        if (ptr < buflen) {
            return true;
        }else{
            ptr = 0;
            try {
                buflen = in.read(buffer);
            } catch (IOException e) {
                e.printStackTrace();
            }
            if (buflen <= 0) {
                return false;
            }
        }
        return true;
    }
    private int readByte() { if (hasNextByte()) return buffer[ptr++]; else return -1;}
    private static boolean isPrintableChar(int c) { return 33 <= c && c <= 126;}
    public boolean hasNext() { while(hasNextByte() && !isPrintableChar(buffer[ptr])) ptr++; return hasNextByte();}
    public String next() {
        if (!hasNext()) throw new NoSuchElementException();
        StringBuilder sb = new StringBuilder();
        int b = readByte();
        while(isPrintableChar(b)) {
            sb.appendCodePoint(b);
            b = readByte();
        }
        return sb.toString();
    }
    public long nextLong() {
        if (!hasNext()) throw new NoSuchElementException();
        long n = 0;
        boolean minus = false;
        int b = readByte();
        if (b == '-') {
            minus = true;
            b = readByte();
        }
        if (b < '0' || '9' < b) {
            throw new NumberFormatException();
        }
        while(true){
            if ('0' <= b && b <= '9') {
                n *= 10;
                n += b - '0';
            }else if(b == -1 || !isPrintableChar(b)){
                return minus ? -n : n;
            }else{
                throw new NumberFormatException();
            }
            b = readByte();
        }
    }
    public int nextInt() {
        long nl = nextLong();
        if (nl < Integer.MIN_VALUE || nl > Integer.MAX_VALUE) throw new NumberFormatException();
        return (int) nl;
    }
    public double nextDouble() { return Double.parseDouble(next());}
}