#include <bits/stdc++.h>
using namespace std;

struct UnionFind{
    vector<int> parent;
    vector<int> size;
    vector<int> rank;

    /* constructor (initialize) */
    UnionFind(int n){
        parent.resize(n);
        size.resize(n);
        rank.resize(n);
        for(int i=0; i<n; i++){
            parent[i] = i;// completely-disjoint
            size[i] = 1;
            rank[i] = 0;// union by rank
        }
    }

    int root(int x){
        // terminal case
        if(parent[x] == x){
            return x;// by definition
        }

        // recursion
        parent[x] = root(parent[x]);// path compression : keep tree as shallow as possible
        return parent[x];
    }

    void merge(int x, int y){
        int rx = root(x);
        int ry = root(y);

        // if (root(x) == root(y)) do nothing;
        if (rx != ry){
            if(rank[rx] < rank[ry]){
                parent[rx] = ry;// root of merged tree = ry
                size[ry] += size[rx];
            }
            else if(rank[rx] == rank[ry]){
                parent[rx] = ry;
                size[ry] += size[rx];
                rank[ry] += 1;
            }
            else if(rank[rx] > rank[ry]){
                parent[ry] = rx;// root of merged tree = rx
                size[rx] += size[ry];
            }
        }
        return;
    }

    bool same(int x, int y){
        return root(x) == root(y);
    }

    int nodes(int x){
        return size[root(x)];
    }
};

/********************************************/

struct edge{
    long long int u, v, cost;
};

bool compare(const edge &e1, const edge &e2){
    return e1.cost < e2.cost;
}

/*******************************************/

int V,E;// number of (vertices, edges)
vector<edge> e(E);

long long int Kruskal(){
    UnionFind tree(V);
    sort(e.begin(), e.end(), compare);// edges sorted by weight-order
    long long int total_cost = 0;
    for (int i=0; i<E; i++){// since edges are sorted, less-weight edge comes first!
	    if (tree.same(e[i].u, e[i].v) == false){// if vertices disconnected,
            tree.merge(e[i].u, e[i].v);// then merge them with it
            total_cost += e[i].cost;
	    }
    }
    return total_cost;// minimum weight
}

int main(){
    long long int n;
    cin >> n;
    V = n;
    E = 2 * (n-1);
    e.resize(E);

    vector<pair<long long int,int>> x(n), y(n);
    for(int i=0; i<n; i++){
        long long int p, q;
        cin >> p >> q;
        x[i] = make_pair(p,i);
        y[i] = make_pair(q,i);
    }
    sort(x.begin(),x.end());
    sort(y.begin(),y.end());
    
    for (int i=0; i<n-1; i++){
        e[i]     = {x[i].second, x[i+1].second, abs(x[i].first-x[i+1].first)};
        e[n-1+i] = {y[i].second, y[i+1].second, abs(y[i].first-y[i+1].first)};
    }
    
    UnionFind uf(V);
    sort(e.begin(), e.end(), compare);// edges sorted by weight-order
    long long int total_cost = 0;
    for (long long int i=0; i<E; i++){// since edges are sorted, less-weight edge comes first!
	    if (uf.same(e[i].u, e[i].v) == false){// if vertices disconnected,
            uf.merge(e[i].u, e[i].v);// then merge them with it
            total_cost += e[i].cost;
	    }
    }
    cout << total_cost << endl;
    return 0;
}

Measured memory_bytes: 9344