#include <iostream>
#include <sstream>
#include <stack>
#include <iomanip>
#include <numeric>
#include <string>
#include <cstring>
#include <algorithm>
#include <functional>
#include <cstdlib>
#include <cassert>
#include <map>
#include <set>
#include <vector>
#include <utility>
#include <queue>
#include <cmath>

#define BEGIN(x) x.begin()
#define END(x) x.end()
#define ALL(x) BEGIN(x), END(x)
#define PAIR make_pair
#define VEC(type) vector<type >
#define endl '\n'
#define FIR first
#define SEC second
#define PB push_back
#define SZ(x) ((int)x.size())

#define FOR(i, A, B) for(auto i = (A);i != (B); i++)
#define FORD(i, A, B) for(auto i = (A);i != (B); i--)

#define READRANGE(begin, end) FOR(it, begin, end) cin >> *it
#define READVEC(V) READRANGE(BEGIN(V), END(V))

using namespace std;

typedef long long lint;
typedef pair<int, int> Pii;
typedef pair<int, lint> Pil;
typedef pair<lint, lint> Pll;
typedef pair<lint, int> Pli;

template<class U, class V>
istream& operator >>(istream& in, pair<U, V>& pr) {
    return in >> pr.first >> pr.second;
}

template<class U, class V>
ostream& operator <<(ostream& out, pair<U, V>& p) {
    return out << p.first << " " << p.second;
}

template<class T>
ostream& operator <<(ostream& out, vector<T> vec) {
    for (T& e : vec)
        out << e << " ";
    return out << endl;
}

// ---- BEGIN LIBRARY CODE ----
// ---- END LIBRARY CODE ----
void io_init()
{
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
};

class DisjointSet
{
public:
    DisjointSet(int _n)
    {
        n = _n;
        root.resize(n);
        height.resize(n);

        for (int i = 0;i < n; i++) {
            root[i] = i;
            height[i] = 0;
        }
    }

    int getRoot(int x)
    {
        if (root[x] == x)
            return x;

        return root[x] = getRoot(root[x]);
    }

    void merge(int x, int y)
    {
        int rx = getRoot(x), ry = getRoot(y);
        if (rx == ry)
            return;

        if (height[rx] < height[ry]) {
            root[rx] = ry;
        } else if (height[rx] > height[ry]) {
            root[ry] = rx;
        } else {
            root[ry] = rx;
            height[rx]++;
        }
    }
private:
    int n;
    vector<int> root, height;
};

void solveSingleCase(int caseNo)
{
    int N;
    cin >> N;
    vector<pair<Pii, int> > xy, yx;
    FOR(i, 0, N) {
        int a, b;
        cin >> a >> b;
        xy.PB(PAIR(Pii(a, b), i));
        yx.PB(PAIR(Pii(b, a), i));
    }

    sort(ALL(xy));
    sort(ALL(yx));

    vector<pair<int, Pii> > Edges;
    FOR(i, 0, N - 1) {
        int x1 = xy[i].FIR.FIR, x2 = xy[i + 1].FIR.FIR;
        int i1 = xy[i].SEC, i2 = xy[i + 1].SEC;
        Edges.PB(PAIR(x2 - x1, Pii(i1, i2)));

        int y1 = yx[i].FIR.FIR, y2 = yx[i + 1].FIR.FIR;
        int j1 = yx[i].SEC, j2 = yx[i + 1].SEC;
        Edges.PB(PAIR(y2 - y1, Pii(j1, j2)));
    }

    sort(ALL(Edges));
    lint ret = 0;
    DisjointSet dset(N);

    for (auto& edge: Edges) {
        int cost = edge.FIR;
        int a = edge.SEC.FIR, b = edge.SEC.SEC;
        if (dset.getRoot(a) != dset.getRoot(b)) {
            ret += cost;
            dset.merge(a, b);
        }
    }

    cout << ret << endl;
};

int main(int argc, char **argv)
{
    io_init();

    // Actual program code starts here.
    int T = 1;
    // cin >> T;
    FOR(tcase, 1, T + 1) {
        solveSingleCase(tcase);
    }
    return 0;
};


Measured memory_bytes: 7340