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



using namespace std;



typedef long long ll;

typedef long double ld;

typedef vector<int> vi;

typedef vector<vector<int> > vvi;

typedef pair<int, int> pii;



#define erep(i, x, n) for (auto i = x; i<=(ll)(n); i++)

#define rep(i, x, n) for(auto i = x; i<(ll)(n); i++)

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

#define sz(v) ((int)((v).size()))

#define mod(n, m) (((n%m) + m)%m)

#define reset(n, m) memset(n, m, sizeof n)

#define endl '\n'



const int N = 1e5 + 5;



vector<pair<ll, int>> node[N];

map<pii, int> idx;

set<pair<ll, int>> st;

vector<pii> vec;



int n, curr = 1;

bool visited[N];



void explore(int v)

{

	visited[v] = true;

	for (auto i : node[v])

		if (!visited[i.second])

			st.insert(

			{ i.first, i.second });

}



int main()

{

	ios_base::sync_with_stdio(0);

	cin.tie(0);



	cin >> n;

	vec.resize(n);

	rep(i, 0, n)

	{

		int a, b;

		cin >> a >> b;



		if (!idx[

		{ a, b }])

			idx[

			{ a, b }] = curr++;

		vec[i] =

		{	a, b};

	}



	sort(all(vec));



	rep(i, 0, n-1)

	{

		int a = idx[vec[i]], b = idx[vec[i + 1]];

		int val = min(abs(vec[i].first - vec[i + 1].first),

				abs(vec[i].second - vec[i + 1].second));



		node[a].push_back(

		{ val, b });

		node[b].push_back(

		{ val, a });

	}



	rep(i, 0, n)

		swap(vec[i].first, vec[i].second);



	sort(all(vec));

	rep(i, 0, n-1)

	{

		int a = idx[

		{ vec[i].second, vec[i].first }], b = idx[

		{ vec[i + 1].second, vec[i + 1].first }];



		int val = min(abs(vec[i].first - vec[i + 1].first),

				abs(vec[i].second - vec[i + 1].second));



		node[a].push_back(

		{ val, b });

		node[b].push_back(

		{ val, a });

	}



	explore(1);



	ll mst = 0;

	// cost, idx, par if needed

	while (!st.empty())

	{

		auto i = st.begin();

		st.erase(st.begin());



		ll cost = i->first, idx = i->second;



		if (!visited[idx])

		{

			mst += cost;

			explore(idx);

		}

	}



	cout << mst << endl;



	return 0;

}


// Faster C++ solution for the same problem (measured speedup: 3.4530606230917584x):
#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";

}