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

using namespace std;

int n,x,y,k;

long long ans=0;

const int inf = 0x3f3f3f3f;

#define ft first

#define se second

const int maxn=100007;

pair <int,int> r[maxn];

pair <int,int> c[maxn];

struct Node{

	int u,v,cst;

}ege[2*maxn+1000];

Node make_node(int a,int b,int c){

	Node node;

	node.u=a;

	node.v=b;

	node.cst=c;

	return node;

}

int f[maxn],rnk[maxn];

int fnd(int x){

	if (f[x]==x)return x;

	return f[x]=fnd(f[x]);

}

void merge(int x,int y){

	x=fnd(x);

	y=fnd(y);

	if (rnk[x]>rnk[y])f[y]=x;

	else {

		f[x]=y;

		if (rnk[x]==rnk[y])rnk[y]++;

	}

}

bool cmp(Node a,Node b){

	return a.cst<b.cst;

}

void K(){

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

		if (fnd(ege[i].u)==fnd(ege[i].v))continue;

		ans+=ege[i].cst;

		merge(ege[i].u,ege[i].v);

//		printf("%lld\n",ans);

	}

	printf("%lld\n",ans);

}

int main(){

	scanf("%d",&n);

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

		scanf("%d%d",&x,&y);

		r[i]=make_pair(x,i);

		c[i]=make_pair(y,i);

	}

	sort(r,r+n);

	sort(c,c+n);

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

		ege[++k]=make_node(r[i-1].se,r[i].se,abs(r[i].ft-r[i-1].ft));

		ege[++k]=make_node(c[i-1].se,c[i].se,abs(c[i].ft-c[i-1].ft));

	}

	sort(ege+1,ege+1+k,cmp);

	memset(f,inf,sizeof f);

	for (int i=0;i<n;++i)f[i]=i,rnk[i]=1;

	K();

	return 0;

}

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

#include <ext/pb_ds/assoc_container.hpp>

#include <ext/pb_ds/tree_policy.hpp>

#include <chrono>



using namespace __gnu_pbds;

using namespace std;



#define ordered_set tree<int, null_type,less<int>, rb_tree_tag,tree_order_statistics_node_update>

// order_of_key (val): returns the no. of values less than val

// find_by_order (k): returns the kth largest element.(0-based)



#define ll long long int

#define ld long double

#define ff first

#define ss second

#define pb push_back

#define pi pair<ll,ll>

#define pii pair<ll,pi >

#define ppi pair<pi,ll>

#define ppp pair<pi,pi >

#define ex(str,a,b) str.substr((int)(a),min((int)str.size()-a,(int)(b-a+1))) 

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

mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());



// for pair comparison function(ascending order) use return (i1.ff < i2.ff);



/* string operations :

   str.substr (x,y) : returns a substring str[x],str[x+1],...str[x+y-1]

   __builtin_popcount(n) : no. of set bits in n.

*/



const int M = (1<<20)+5;

const int md = 1e9+7;



priority_queue<pi,vector<pi >,greater<pi > > pq;



ll pwr(ll a,ll n,ll m)

{

	ll p=1;

	while(n>0)

	{

		if(n%2==1)

			p=(p*a)%m;

		a=(a*a)%m;

		n=n/2;

	}

	return p;

}



ll ax[M],ay[M];

set<pii > px,py,nx,ny;

bool mrk[M];



int main()

{

	ios::sync_with_stdio(false);

	cin.tie(0);

	cout.tie(0);



	ll n,i,x,y,d,cost = 0;



	cin >> n;

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

	{

		cin >> x >> y;

		px.insert(pii(x,pi(y,i)));

		nx.insert(pii(-1*x,pi(y,i)));

		py.insert(pii(y,pi(x,i)));

		ny.insert(pii(-1*y,pi(x,i)));

		ax[i] = x;

		ay[i] = y;

	}



	pq.push(pi(0,1));



	while(!pq.empty())

	{

		pi ed = pq.top();

		pq.pop();

		d = ed.ff;

		i = ed.ss;

		if(mrk[i])

			continue;

		mrk[i] = 1;

		cost += d;

		px.erase(pii(ax[i],pi(ay[i],i)));

		nx.erase(pii(-1*ax[i],pi(ay[i],i)));

		py.erase(pii(ay[i],pi(ax[i],i)));

		ny.erase(pii(-1*ay[i],pi(ax[i],i)));



		auto gx = px.upper_bound(pii(ax[i],pi(-1,-1)));

		if(gx != px.end())

			pq.push(pi(min(abs((*gx).ff-ax[i]),abs((*gx).ss.ff-ay[i])),(*gx).ss.ss));

		gx = nx.upper_bound(pii(-1*ax[i],pi(-1,-1)));

		if(gx != nx.end())

			pq.push(pi(min(abs(-1*((*gx).ff)-ax[i]),abs((*gx).ss.ff-ay[i])),(*gx).ss.ss));

		gx = py.upper_bound(pii(ay[i],pi(-1,-1)));

		if(gx != py.end())

			pq.push(pi(min(abs((*gx).ff-ay[i]),abs((*gx).ss.ff-ax[i])),(*gx).ss.ss));

		gx = ny.upper_bound(pii(-1*ay[i],pi(-1,-1)));

		if(gx != ny.end())

			pq.push(pi(min(abs((*gx).ss.ff-ax[i]),abs(-1*((*gx).ff)-ay[i])),(*gx).ss.ss));

	}



	cout << cost << "\n";

}