// tested by Hightail - https://github.com/dj3500/hightail
import std.stdio, std.string, std.conv, std.algorithm;
import std.range, std.array, std.math, std.typecons, std.container, core.bitop;

int n;

void main() {
    scan(n);

    alias Point = Tuple!(int, "x", int, "y", int, "idx");

    auto xys = new Point[](n);

    int xi, yi;

    foreach (i ; 0 .. n) {
        scan(xi, yi);
        xys[i] = Point(xi, yi, i);
    }

    debug {
        writeln(xys);
    }

    alias Edge = Tuple!(int, "c", int, "u", int, "v");

    auto es = new Edge[](0);

    xys.sort();

    foreach (i ; 0 .. n) {
        if (i + 1 < n) es ~= Edge(xys[i + 1].x - xys[i].x, xys[i].idx, xys[i + 1].idx);
    }

    xys.sort!"a[1] < b[1]"();

    foreach (i ; 0 .. n) {
        if (i + 1 < n) es ~= Edge(xys[i + 1].y - xys[i].y, xys[i].idx, xys[i + 1].idx);
    }

    es.sort();

    debug {
        writeln(es);
    }

    auto uf = new UnionFind(n);
    long ans;
    int cnt;

    foreach (i ; 0 .. es.length) {
        if (uf.same(es[i].u, es[i].v)) continue;

        uf.unite(es[i].u, es[i].v);
        ans += es[i].c;
        cnt++;

        if (cnt == n - 1) break;
    }

    writeln(ans);
}


void scan(T...)(ref T args) {
    string[] line = readln.split;
    foreach (ref arg; args) {
        arg = line.front.to!(typeof(arg));
        line.popFront();
    }
    assert(line.empty);
}

class UnionFind
{
private:
    int[] p;
    int[] rank;

public:
    this(int N)
    {
        p = iota(N).array;
        rank = new int[](N);
    }

    int find_root(int x)
    {
        if(x != p[x]) p[x] = find_root(p[x]);
        return p[x];
    }

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

    void unite(int x, int y)
    {
        x = find_root(x);
        y = find_root(y);

        if (x == y) return;

        if (rank[x] < rank[y]) {
            p[x] = y;
        }
        else {
            p[y] = x;

            if (rank[x] == rank[y]) rank[x]++;
        }
    }
}
