// Original C++ solution (slower):
#include <iostream>

#include <vector>

#include <string>

#include <cstring>

#include <algorithm>

#include <cmath>

#include <set>

#include <map>

#include <queue>

#include <iomanip>

#include <cassert>

#include <random>

#include <tuple>



#define rep(i,n) for (int i = 0; i < (n); ++i)



using namespace std;

typedef long long ll;

typedef pair<int, int> P;



struct edge {int to; int cost;};

vector<edge> g[100100];

int dist[100100];

bool memo[100100];

const int INF = 1100100100;





void prim(int v) {

    priority_queue<P, vector<P>, greater<P> > q;

    fill(dist, dist+100100, INF);

    dist[v] = 0;

    q.push(P(0, v));

    while (!q.empty()) {

        P p = q.top(); q.pop();

        int cost = p.first;

        int node = p.second;

        memo[node] = 1;

        if (cost > dist[node]) continue;

        for (auto e: g[node]) {

            if (dist[e.to] > e.cost && !memo[e.to]) {

                dist[e.to] = e.cost;

                q.push(P(e.cost, e.to));

            }

        }

    }

}



int main() {

    int n;

    cin >> n;

    vector<P> x(n), y(n);

    rep(i,n) {

        cin >> x[i].first >> y[i].first;

        x[i].second = i;

        y[i].second = i;

    }

    

    sort(x.begin(), x.end());

    rep(i,n-1) {

        g[x[i].second].push_back({x[i+1].second, x[i+1].first - x[i].first});

        g[x[i+1].second].push_back({x[i].second, x[i+1].first - x[i].first});

    }



    sort(y.begin(), y.end());

    rep(i,n-1) {

        g[y[i].second].push_back({y[i+1].second, y[i+1].first - y[i].first});

        g[y[i+1].second].push_back({y[i].second, y[i+1].first - y[i].first});

    }



    prim(0);

    int all_cost = 0;

    rep(i,n) all_cost += dist[i];

    cout << all_cost << endl;



    return 0;

}


// Optimized solution to the same problem (faster):
#include <iostream>

#include <vector>

#include <string>

#include <cstring>

#include <algorithm>

#include <cmath>

#include <set>

#include <map>

#include <queue>

#include <iomanip>

#include <cassert>

#include <random>

#include <tuple>



#define rep(i,n) for (int i = 0; i < (n); ++i)



using namespace std;

typedef long long ll;

typedef pair<int, int> P;



class UnionFind {

public:

    int n;

    vector<int> parent;

    vector<int> rank;

    UnionFind(int m) {

        n = m;

        parent.resize(n);

        rank.resize(n, 0);

        for (int i = 0; i < n; i++) {

            parent[i] = i;

        }

    }



    int find(int node) {

        if (parent[node] == node) {

            return node;

        } else {

            parent[node] = find(parent[node]);

            return parent[node];

        }

    }



    void unite(int node1, int node2) {

        node1 = find(node1);

        node2 = find(node2);

        if (node1 == node2) {

            return;

        } else {

            if (rank[node1] < rank[node2]) {

                parent[node1] = node2;

            } else if (rank[node1] > rank[node2]) {

                parent[node2] = node1;

            } else {

                parent[node1] = node2;

                rank[node1] += 1;

            }

        }

    }



    bool same(int node1, int node2) {

        node1 = find(node1);

        node2 = find(node2);

        if (node1 == node2) {

            return true;

        } else {

            return false;

        }

    }

};



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

vector<edge> g;

bool compare(const edge &a, const edge &b) {

    return a.cost < b.cost;

}



int main() {

    int n;

    cin >> n;

    vector<P> x(n), y(n);

    rep(i, n) {

        cin >> x[i].first >> y[i].first;

        x[i].second = i;

        y[i].second = i;

    }



    sort(x.begin(), x.end());

    sort(y.begin(), y.end());

    rep(i, n-1) {

        g.push_back({x[i].second, x[i+1].second, x[i+1].first - x[i].first});

        g.push_back({y[i].second, y[i+1].second, y[i+1].first - y[i].first});

    }



    sort(g.begin(), g.end(), compare);



    UnionFind uf(n);

    int ans = 0;

    rep(i, g.size()) {

        if (!uf.same(g[i].u, g[i].v)) {

            uf.unite(g[i].u, g[i].v);

            ans += g[i].cost;

        }

    }



    cout << ans << endl;

    

    return 0;

}


// Fastest known solution for this problem: