// Slower C++ solution:
#include <bits/stdc++.h>

#include <ext/pb_ds/assoc_container.hpp>

#include <ext/pb_ds/tree_policy.hpp>



using namespace std;

using namespace __gnu_pbds;



#define fi first

#define se second

#define mp make_pair

#define pb push_back

#define fbo find_by_order

#define ook order_of_key



typedef long long ll;

typedef pair<ll,ll> ii;

typedef vector<int> vi;

typedef long double ld;

typedef tree<int, null_type, less<int>, rb_tree_tag, tree_order_statistics_node_update> pbds;

bool marked[100001];

vector<ii> v[100001];  //adjList



ll prim(int k){

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

    ll u;

    long long minimumCost = 0;

    ii p;

    q.push(mp(0, k));

    while(!q.empty())

    {

        p = q.top();

        q.pop();

        k = p.second;

        if(marked[k] == true)

            continue;

        minimumCost += p.fi;

        marked[k] = true;

        for(ll i = 0;i < v[k].size();++i)

        {

            u = v[k][i].se;

            if(marked[u] == false)

                q.push(v[k][i]);

        }

    }

    return minimumCost;

}



int main() {

    std::ios::sync_with_stdio(false);

    cin.tie(NULL);

    long long n;

    cin>>n;

    vector<ii> x;

    vector<ii> y;

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

        ll a,b;

        cin>>a>>b;

        x.pb(mp(a,i));

        y.pb(mp(b,i));

    }

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

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

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

        v[x[i].se].pb(mp(x[i+1].fi-x[i].fi,x[i+1].se));

        v[x[i+1].se].pb(mp(x[i+1].fi-x[i].fi,x[i].se));

        v[y[i].se].pb(mp(y[i+1].fi-y[i].fi,y[i+1].se));

        v[y[i+1].se].pb(mp(y[i+1].fi-y[i].fi,y[i].se));

    }

    ll ans=prim(0);

    cout<<ans;

    return 0;

}


// Faster C++ solution for the same problem (measured speedup: 3.536799203154692x):
#include<bits/stdc++.h>

using namespace std;



#define int long long

#define fi first

#define se second

const int oo = 1e9 + 7;

typedef pair<int, int> ii;

typedef pair<ii, int> iii;



int n, par[100001], sz[100001];

vector<iii> point, edg;



int dist(int a, int b, int c, int d){

	return min(abs(a - c), abs(b - d));

}



int anc(int x){

	if(par[x] == -1) return x;

	else return (par[x] = anc(par[x]));

}



bool issameset(int x, int y){ return (anc(x) == anc(y));}



void uni(int x, int y){

	x = anc(x);

	y = anc(y);

	if(sz[x] > sz[y]){

		sz[x] += sz[y];

		par[y] = x;

	}

	else{

		sz[y] += sz[x];

		par[x] = y;

	}

}



bool cmp(iii a, iii b){

	return a.se < b.se;

}



signed main(){

	cin >> n;

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

		iii pt;

		cin >> pt.fi.fi >> pt.fi.se;

		pt.second = i;

		point.push_back(pt);

	}

	point.push_back(make_pair(make_pair(-oo, -oo), 0));

	point.push_back(make_pair(make_pair(2 * oo, 2 * oo), 0));

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

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

	    edg.push_back(make_pair(make_pair(point[i].se, point[i - 1].se), dist(point[i].fi.fi, point[i].fi.se, point[i - 1].fi.fi, point[i - 1].fi.se)));

	}

	for(int i = 1; i <= n; i++) swap(point[i].fi.fi, point[i].fi.se);

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

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

	    edg.push_back(make_pair(make_pair(point[i].se, point[i - 1].se), dist(point[i].fi.fi, point[i].fi.se, point[i - 1].fi.fi, point[i - 1].fi.se)));

	}

	//cout << edg[3].fi.fi << " " << edg[3].fi.se << endl;

	for(int i = 1; i <= n; i++) par[i] = -1;

	sort(edg.begin(), edg.end(), cmp);

	int ans = 0;

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

	    //cout << edg[i].fi.fi << " " << edg[i].fi.se << " " << edg[i].se << " ";

	    if(!issameset(edg[i].fi.fi, edg[i].fi.se)){

	        //cout << 1;

	        ans += edg[i].se;

	        uni(edg[i].fi.fi, edg[i].fi.se);

	    }

	    cout << endl;

	}

	cout << ans;

}