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



using namespace std;



typedef long long ll;

typedef unsigned long long ull;

typedef vector<int> vi;

typedef vector<ll> vl;

typedef pair<int, int> pii;

typedef pair<ll, ll> pll;



#define REP(i, n) for(int i=0; i<(n); ++i)

#define FOR(i, a, b) for(int i=(a); i<(b); ++i)

#define FORR(i, a, b) for(int i=(b)-1; i>=(a); --i)



#define DEBUG(x) cout<<#x<<": "<<x<<'\n'

#define DEBUG_VEC(v) cout<<#v<<":";REP(i, v.size())cout<<' '<<v[i];cout<<'\n'

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



#define CHMIN(a, b) a=min((a), (b))

#define CHMAX(a, b) a=max((a), (b))



const ll MOD=1000000007ll;

// const ll MOD=998244353ll;

#define FIX(a) ((a)%MOD+MOD)%MOD



const double EPS=1e-11;

#define EQ0(x) (abs((x))<EPS)

#define EQ(a, b) (abs((a)-(b))<EPS)



const ll INF=1e18;

const int MAX_N=114514;

const int MAX_E=214514;



struct edge{

	pii u;

	pii v;

	int cost;

};



int root[MAX_N], depth[MAX_N];



edge es[MAX_E];

int V, E;



bool comp(const edge& e1, const edge& e2){

	return e1.cost<e2.cost;

}



// n要素で初期化

void init_union_find(int n){

	REP(i, n){

		root[i]=i;

		depth[i]=0;

	}

}



// xの根を求める

int find(int x){

	if(root[x]==x){

		return x;

	}

	else{

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

	}

}



// xとyが属する集合を併合

void unite(int x, int y){

	x=find(x);

	y=find(y);

	if(x==y){

		return;

	}

	if(depth[x]<depth[y]){

		root[x]=y;

	}

	else{

		root[y]=x;

		if(depth[x]==depth[y]){

			++depth[x];

		}

	}

	return;

}



// xとyが同じ集合に属するか判定

bool same(int x, int y){

	return find(x)==find(y);

}



ll kruskal(){

	sort(es, es+E, comp);

	init_union_find(V);

	ll res=0;

	REP(i, E){

		edge e=es[i];

		if(!same(e.u.second, e.v.second)){

			unite(e.u.second, e.v.second);

			res+=e.cost;

		}

	}

	return res;

}



int main(){

	ios::sync_with_stdio(false);

	cin.tie(0);

	int n;

	pii x[114514], y[114514];

	cin>>n;

	V=n;

	E=2*(n-1);

	REP(i, n){

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

		x[i].second=i;

		y[i].second=i;

	}

	sort(x, x+n);

	REP(i, n-1){

		edge e;

		e.u=x[i];

		e.v=x[i+1];

		e.cost=e.v.first-e.u.first;

		es[i]=e;

	}

	sort(y, y+n);

	REP(i, n-1){

		edge e;

		e.u=y[i];

		e.v=y[i+1];

		e.cost=e.v.first-e.u.first;

		es[n-1+i]=e;

	}

	cout<<kruskal()<<'\n';

	return 0;

}


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



using namespace std;



typedef long long ll;

typedef unsigned long long ull;

typedef vector<int> vi;

typedef vector<ll> vl;

typedef pair<int, int> pii;

typedef pair<ll, ll> pll;



#define REP(i, n) for(int i=0; i<(n); ++i)

#define FOR(i, a, b) for(int i=(a); i<(b); ++i)

#define FORR(i, a, b) for(int i=(b)-1; i>=(a); --i)



#define DEBUG(x) cout<<#x<<": "<<x<<'\n'

#define DEBUG_VEC(v) cout<<#v<<":";REP(i, v.size())cout<<' '<<v[i];cout<<'\n'

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



#define CHMIN(a, b) a=min((a), (b))

#define CHMAX(a, b) a=max((a), (b))



const ll MOD=1000000007ll;

// const ll MOD=998244353ll;

#define FIX(a) ((a)%MOD+MOD)%MOD



const double EPS=1e-11;

#define EQ0(x) (abs((x))<EPS)

#define EQ(a, b) (abs((a)-(b))<EPS)



const ll INF=1e18;

const int MAX_N=114514;

const int MAX_E=214514;



struct UnionFind{

	vector<int> par;

	vector<int> rank;



	UnionFind(int n=1){

		init(n);

	}



	// n要素で初期化

	void init(int n=1){

		par.resize(n);

		rank.resize(n);

		REP(i, n){

			par[i]=i;

			rank[i]=0;

		}

	}



	// xの根を求める

	int find(int x){

		if(par[x]==x){

			return x;

		}

		else{

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

		}

	}



	// xとyが属する集合を併合

	bool unite(int x, int y){

		x=find(x);

		y=find(y);

		if(x==y){

			return false;

		}

		if(rank[x]<rank[y]){

			par[x]=y;

		}

		else{

			par[y]=x;

			if(rank[x]==rank[y]){

				++rank[x];

			}

		}

		return true;

	}



	// xとyが同じ集合に属するか判定

	bool is_same(int x, int y){

		return find(x)==find(y);

	}

};



struct edge{

	int u;

	int v;

	int cost;

};



int root[MAX_N], depth[MAX_N];



edge es[MAX_E];

int V, E;



void add_edge(int u, int v, int cost){

	edge e;

	e.u=u;

	e.v=v;

	e.cost=cost;

	es[E++]=e;

	return;

}



bool comp(const edge& e1, const edge& e2){

	return e1.cost<e2.cost;

}



ll kruskal(){

	sort(es, es+E, comp);

	UnionFind uf(V);

	ll res=0;

	REP(i, E){

		edge e=es[i];

		if(!uf.is_same(e.u, e.v)){

			uf.unite(e.u, e.v);

			res+=e.cost;

		}

	}

	return res;

}



int main(){

	ios::sync_with_stdio(false);

	cin.tie(0);

	int n;

	pii x[114514], y[114514];

	cin>>n;

	V=n;

	REP(i, n){

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

		x[i].second=i;

		y[i].second=i;

	}

	sort(x, x+n);

	REP(i, n-1){

		add_edge(x[i].second, x[i+1].second, x[i+1].first-x[i].first);

	}

	sort(y, y+n);

	REP(i, n-1){

		add_edge(y[i].second, y[i+1].second, y[i+1].first-y[i].first);

	}

	cout<<kruskal()<<'\n';

	return 0;

}