#include <bits/stdc++.h> 

using namespace std;

#define fcout(d) cout << fixed << setprecision(d)
#define rep(i,n) for(int (i)=0; (i)<n; ++(i))
#define rep1(i,n) for(int (i)=1; (i)<=n; ++(i))
#define repU(i,bottom,ceiling) for(int (i) = (bottom); (i) <= (ceiling); ++(i))
#define repD(i,ceiling,bottom) for(int (i) = (ceiling); (i) >= (bottom); --(i))
#define pub push_back
#define pob pop_back
#define prf printf
#define scf scanf
#define mkp make_pair
#define fir first
#define sec second
#define clr(a) memset((a),0,sizeof(a))

typedef long long ll;
typedef double db;

const vector<pair<int,int>> DIR = { {1,0},{0,1},{-1,0},{0,-1},{1,1},{-1,1},{-1,-1},{1,-1} };
const int INF = (int)2e9 + 1e8;
const int MOD = (int)1e9 + 7;

template<typename T,typename U>                                                   
inline pair<T,U> operator+(const pair<T,U> & l,const pair<T,U> & r) {   
    return {l.fir+r.fir,l.sec+r.sec};                                    
} 

template<typename T,typename U> 
inline pair<T,U> operator-(const pair<T,U> & l,const pair<T,U> & r) {   
    return {l.fir-r.fir,l.sec-r.sec};                                    
} 

template<typename T,typename U>                                                   
inline pair<T,U> operator*(const pair<T,U> & l,const pair<T,U> & r) {   
    return {l.fir*r.fir,l.sec*r.sec};                                    
}

template<typename T> inline T gcd(T a,T b){ if(a % b){ return gcd(b,a % b); }else{ return b; } }

template<typename T> inline T lcm(T a,T b){ return a / gcd(a,b) * b; }

inline int Pow(const long long n,long long m,const int mod = MOD){
	long long res = 1,pow = n;
	while(m) {
		if(m & 1) res = (res * pow) % mod;
		pow = (pow * pow) % mod;
		m >>= 1;
	}
	return res;
}

inline vector<int> Frac(const int range,const int mod = MOD){
	vector<int> frac;
	frac.push_back(1);
	for(int i = 1; i <= range; ++i) frac.push_back((long long)frac.back() * i % mod);
	return frac;
}

inline int Comb(const int n,const int m,const int mod = MOD){
	if(n < m || m < 0) return 0;
	vector<int> frac(Frac(n,mod));
	long long rev = Pow((long long)frac[m] * frac[n-m] % mod,mod-2,mod);
	return rev * frac[n] % mod;
}

template<typename T> inline bool v_find(const vector<T> v,const T obj){
	auto itr = find(v.begin(), v.end(), obj);
	size_t index = distance(v.begin(),itr);
	if (index != v.size()) { return true; }
	return false; 
}

template<typename T> inline bool v_erase(vector<T> &v,const T obj){
	auto itr = find(v.begin(), v.end(), obj);
	size_t index = distance(v.begin(),itr);
	if (index != v.size()) {
		v.erase(itr);
		return true;
	}
	return false;	
}

template<class T,class U> inline auto LB(const T v,const U in){ return lower_bound(v.begin(),v.end(),in); }

template<class T,class U> inline auto UB(const T v,const U in){ return upper_bound(v.begin(),v.end(),in); }




template<class Abel> struct UnionFind {
	vector<int> par;
	vector<int> size;
	vector<int> rank;
	vector<Abel> diff_weight;

	UnionFind(int n) {
		init(n);
	}

	void init(int n) {
		par.resize(n);
		size.resize(n);
		rank.resize(n);
		diff_weight.resize(n);
		for (int i = 0; i < n; ++i) {
			par[i] = i;
			size[i] = 1;
			rank[i] = 0;
		}
	}

	int root(int x) {
		if (par[x] == x) {
			return x;
		} else { 
			int r = root(par[x]);
			size[x] = size[r];
			diff_weight[x] += diff_weight[par[x]];
			return par[x] = r;
		}
	}
	
	int scale(int x){
		return size[root[x]];
	}

	Abel weight(int x) {
		root(x);
		return diff_weight[x];
	} 

	Abel diff(int x, int y) {
		return weight(y) - weight(x);
	} 

	bool issame(int x, int y) {
		return root(x) == root(y);
	}

	bool merge(int x, int y, int w = 0) {
		w += weight(x);
		w -= weight(y);
		x = root(x);
		y = root(y);
		if (x == y) return false;
		if (rank[x] < rank[y]) {
			swap(x,y);
			w = -w;
		}
		if (rank[x] == rank[y]) rank[x]++;
		size[x] += size[y];
		par[y] = x;
		diff_weight[y] = w;
		return true;
	}
};

int n,x[100001],y[100001],a[100001],b[100001];
vector<tuple<int,int,int>> edg;

bool x_cmp(int p,int q){
	return x[p]<x[q];
}

bool y_cmp(int p,int q){
	return y[p]<y[q];
}

bool edg_cmp(tuple<int,int,int> e1,tuple<int,int,int> e2){
	return get<2>(e1)<get<2>(e2);
}

inline void solve(){
	sort(a,a+n,x_cmp);
	sort(b,b+n,y_cmp);
	rep(i,n-1){
		edg.pub(make_tuple(a[i],a[i+1],x[a[i+1]]-x[a[i]]));
		edg.pub(make_tuple(b[i],b[i+1],y[b[i+1]]-y[b[i]]));
	}
	sort(edg.begin(),edg.end(),edg_cmp);
	UnionFind<int> uf(n);
	int ans=0;
	rep(i,edg.size()){
		int v1=get<0>(edg[i]);
		int v2=get<1>(edg[i]);
		if(!uf.issame(v1,v2)){
			uf.merge(v1,v2);
			ans+=get<2>(edg[i]);
		}
	}
	cout<<ans<<endl;
	return;
}

inline void input(){
	cin>>n;
	rep(i,n){
		cin>>x[i]>>y[i];
		a[i]=b[i]=i;
	}
	return;
}

int main(){
	cin.tie(0);
	ios::sync_with_stdio(false);
	input();
	solve();
	return 0;
}




Measured memory_bytes: 6388