// Original C++ solution (slower):
#include <bits/stdc++.h>

using namespace std;



int uni[100010];

void init(){

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

        uni[i] = i;

    }

}



int root(int i){

    if(uni[i] == i) return i;

    return uni[i] = root(uni[i]);

}



void unite(int i, int j){

    i = root(i);

    j = root(j);

    if(i != j){

        uni[max(i, j)] = min(i, j);

    }

    return;

}



bool same(int i, int j){

    return root(i) == root(j);

}



#define P pair<long long, pair<int ,int> >



int main(){

    int n;

    cin >> n;



    pair<long long, int> x[100010], y[100010];



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

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

        x[i].second = y[i].second = i;

    }



    sort(x, x+n);

    sort(y, y+n);



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

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

        que.push(make_pair(x[i+1].first-x[i].first, make_pair(x[i].second, x[i+1].second)));

        que.push(make_pair(y[i+1].first-y[i].first, make_pair(y[i].second, y[i+1].second)));

    }



    long long ans = 0;

    init();



    while(!que.empty()){

        int idx1 = que.top().second.first;

        int idx2 = que.top().second.second;

        long long cost = que.top().first;

        que.pop();

        if(!same(idx1, idx2)){

            unite(idx1, idx2);

            ans += cost;

        }

    }



    cout << ans << endl;

    return 0;

}






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

#include <cfloat>

#include <climits>

#include <cmath>

#include <csignal>

#include <cstdarg>

#include <cstddef>

#include <cstdio>

#include <cstdlib>

#include <cstring>

#include <ctime>

 

#include <algorithm>

#include <bitset>

#include <complex>

#include <deque>

#include <ios>

#include <iostream>

#include <istream>

#include <iterator>

#include <limits>

#include <list>

#include <locale>

#include <map>

#include <memory>

#include <new>

#include <numeric>

#include <ostream>

#include <queue>

#include <set>

#include <sstream>

#include <stack>

#include <string>

#include <utility>

#include <valarray>

#include <vector>

 

#if __cplusplus >= 201103L

#include <array>

#include <forward_list>

#include <random>

#include <regex>

#include <scoped_allocator>

#include <system_error>

#include <thread>

#include <tuple>

#include <typeindex>

#include <unordered_map>

#include <unordered_set>

#endif

 

#define F first

#define S second

#define MP make_pair

#define pb push_back

#define all(a) a.begin(), a.end()

#define lcm( a, b ) (a)/__gcd((a),(b))*(b)

#define endl '\n'

 

using namespace std;

 

typedef long long LL;

typedef pair< int, int > P;

typedef pair< LL, LL > LP;

typedef pair< P, int > Pi;

typedef pair< P, P > PP;

 

static const int INF = INT_MAX;

static const LL LINF = LLONG_MAX;

static const int MIN = INT_MIN;

static const LL LMIN = LLONG_MIN;

static const int MOD = 1000000007;

static const int SIZE = 100005;

 

const int dx[] = {0, -1, 1, 0};

const int dy[] = {-1, 0, 0, 1};

 

vector< int > Div( int n ) {

    vector< int > ret;

    for( int i = 1; i * i <= n; ++i ) {

        if( n % i == 0 ) {

            ret.pb( i );

 

            if( i * i != n ) ret.pb( n / i );

        }

    }

    sort( all( ret ) );

    return ret;

}

 

int Root( int x );

bool Unite( int x, int y );

LL Kruskal();

 

vector< pair< LL, P > > edge;

int root[SIZE];

 

int main() {

    ios::sync_with_stdio(false);

    cin.tie(0);

 

    int n;

    cin >> n;

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

        root[i] = i;

 

    }

 

    vector< LP > x_edge, y_edge;

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

        LL x, y;

        cin >> x >> y;

        x_edge.pb( MP( x, i ) );

        y_edge.pb( MP( y, i ) );

 

    }

    sort( all( x_edge ) );

    sort( all( y_edge ) );

 

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

        LL x_min_cost = abs( x_edge[i].F - x_edge[i + 1].F );

        LL y_min_cost = abs( y_edge[i].F - y_edge[i + 1].F );

 

        edge.pb( MP( x_min_cost, MP( x_edge[i].S, x_edge[i + 1].S ) ) );

        edge.pb( MP( y_min_cost, MP( y_edge[i].S, y_edge[i + 1].S ) ) );

 

    }

 

    cout << Kruskal() << endl;

 

    return 0;

}

 

int Root( int x ) {

    if( x == root[x] ) {

        return x;

 

    }

 

    return root[x] = Root( root[x] );

 

}

 

bool Unite( int x, int y ) {

    int rx, ry;

    rx = Root( x );

    ry = Root( y );

    if( rx == ry ) {

        return false;

 

    }

 

    if( rx > ry ) {

        root[ry] = rx;

 

    } else {

        root[rx] = ry;

 

    }

    return true;

 

}

 

LL Kruskal() {

    sort( all( edge ) );

 

    LL res = 0;

    for( int i = 0; i < edge.size(); ++i ) {

        if( Unite( edge[i].S.F, edge[i].S.S ) ) {

            res += edge[i].F;

 

        }

    }

 

    return res;

}

// Fastest known solution for this problem: