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

using namespace std;

#define int long long

vector<pair<int,pair<int,int> > >points;

vector<pair<int,pair<int,int> > > edge;

int par[100005];

bool cmp(pair<int,pair<int,int> > &a,pair<int,pair<int,int> > &b ){

	return a.second.first<b.second.first;

}

bool cmp2(pair<int,pair<int,int> > &a,pair<int,pair<int,int> > &b ){

	return a.second.second<b.second.second;

}

void init(){

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

		par[i]=i;

	}

}

int find(int i){

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

	return par[i]=find(par[i]);

}

void dsu(int i,int j){

	par[find(i)]=find(j);

}

bool same(int i,int j){

	return find(i)==find(j);

}

signed main(){

//	freopen("plantree.inp","w",stdin);

//	freopen("plantree.out","r",stdout);

	ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);

	int n;

	cin>>n;

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

		int x,y;

		cin>>x>>y;

		points.push_back(make_pair(i,make_pair(x,y)));

	}	

	init();

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

	for(int i=1;i<points.size();i++){

		edge.push_back(make_pair(points[i].second.first-points[i-1].second.first,make_pair(points[i].first,points[i-1].first)));

	}

	sort(points.begin(),points.end(),cmp2);

	for(int i=1;i<points.size();i++){

		edge.push_back(make_pair(points[i].second.second-points[i-1].second.second,make_pair(points[i].first,points[i-1].first)));

	}

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

	int ans=0;

	

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

		if(!same(edge[i].second.second,edge[i].second.first)){

			ans+=edge[i].first;

			dsu(edge[i].second.second,edge[i].second.first);

		}

	}

	cout<<ans;

}

// Faster C++ solution for the same problem (measured speedup: 1.7902289891870526x):
#define _CRT_SECURE_NO_DEPRECATE

#pragma comment(linker, "/STACK:102400000,102400000")

#include<iostream>  

#include<cstdio>  

#include<fstream>  

#include<iomanip>

#include<algorithm>  

#include<cmath>  

#include<deque>  

#include<vector>  

#include<assert.h>

#include<bitset>

#include<queue>  

#include<string>  

#include<cstring>  

#include<map>  

#include<stack>  

#include<set>

#include<functional>

#define pii pair<int, int>

#define mod 1000000007

#define mp make_pair

#define pi acos(-1)

#define eps 0.00000001

#define mst(a,i) memset(a,i,sizeof(a))

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

#define lson(x) ((x<<1))  

#define rson(x) ((x<<1)|1) 

#define inf 0x3f3f3f3f

typedef long long ll;

typedef unsigned long long ull;

using namespace std;

const int maxn = 1e5 + 5;

class node {

public:

    int u, v, w;

    node(int a, int b, int c) :u(a), v(b), w(c) {};

};

int fa[maxn];

int getf(int i) { return i == fa[i] ? i : fa[i] = getf(fa[i]); }

vector<node>edge;

bool cmp(const node&a, const node&b){return a.w < b.w;}

class T {

public:

    int value, id;

    bool operator<(const T &a){return value < a.value;}

};

T sx[maxn], sy[maxn];

int main()

{

    ios::sync_with_stdio(false);

    cin.tie(0);

    int i, j, k, m, n, ta, tb;

    cin >> n;

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

        fa[i] = i;

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

    {

        cin >> sx[i].value >> sy[i].value;

        sx[i].id = sy[i].id = i;

    }

    sort(sx + 1, sx + n + 1);

    sort(sy + 1, sy + 1 + n);

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

    {

        edge.push_back(node(sx[i].id, sx[i + 1].id, sx[i+1].value - sx[i].value));

        edge.push_back(node(sy[i].id, sy[i + 1].id, sy[i+1].value - sy[i].value));

    }

    sort(all(edge), cmp);

    ll ans = 0;

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

    {

        if (getf(edge[i].u) != getf(edge[i].v))

        {

           ans += edge[i].w;

           fa[getf(edge[i].u)] = getf(edge[i].v);

        }

    }

    cout << ans << endl;

    return 0;

}