// Slower C++ solution:
#include<iostream>

#include<fstream>

#include<sstream>

#include<algorithm>

#include<cstdio>

#include<cassert>

#include<cmath>

#include<cstdlib>

#include<cstring>

#include<string>

#include<deque>

#include<queue>

#include<vector>

#include<list>

#include<map>

#include<set>

#include<bitset>

#include<stack>

#include<iomanip>

#include<utility>

#include<functional>

using namespace std;

int n,m;

int ans;

int par[100005];

vector<int> edge[100005];

vector<pair<int,int> > el;

pair<int,int> e[200005];

pair<pair<int,int>,int> a[100005],b[100005];

int find(int x)

{

	if(par[x]!=x)

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

	else

		return par[x];

}

bool unite(int x,int y)

{

	x=find(x);

	y=find(y);

	if(x==y)

		return false;

	else

	{

		par[x]=y;

		return true;

	}

}

int main()

{

	cin>>n;

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

	{

		cin>>a[i].first.first>>a[i].first.second;

		b[i].first.first=a[i].first.second;

		b[i].first.second=a[i].first.first;

		a[i].second=b[i].second=i;

	}

	sort(a,a+n);

	sort(b,b+n);

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

	{

		edge[a[i].second].push_back(a[i-1].second);

		e[m]=make_pair(a[i].second,a[i-1].second);

		el.push_back(make_pair(a[i].first.first-a[i-1].first.first,m++));

	}

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

	{

		edge[b[i].second].push_back(b[i-1].second);

		e[m]=make_pair(b[i].second,b[i-1].second);

		el.push_back(make_pair(b[i].first.first-b[i-1].first.first,m++));

	}

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

		par[i]=i;

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

	for(int i=0;i<m;i++)

	{

		int xx=e[el[i].second].first;

		int yy=e[el[i].second].second;

		if(unite(xx,yy))

			ans+=el[i].first;

	}

	cout<<ans;

	return 0;

}


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

using namespace std;

//#define cerr if (false) cerr

#define db(x) cerr << #x << "=" << x << endl

#define db2(x, y) cerr << #x << "=" << x << "," << #y << "=" << y << endl

#define db3(x, y, z) cerr << #x << "=" << x << "," << #y << "=" << y << "," << #z << "=" << z << endl

#define dbv(v) cerr << #v << "="; for (auto _x : v) cerr << _x << ", "; cerr << endl

#define dba(a, n) cerr << #a << "="; for (int _i = 0; _i < (n); ++_i) cerr << a[_i] << ", "; cerr << endl

template <typename A, typename B>

ostream& operator<<(ostream& os, const pair<A, B>& x) {

	return os << "(" << x.first << "," << x.second << ")";

}

typedef long long ll;

typedef long double ld;

int main() {

	int n;

	scanf("%d", &n);

	vector<int> X(n), Y(n), id(n);

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

		scanf("%d%d", &X[i], &Y[i]);

		id[i] = i;

	}

	vector<pair<int, pair<int, int>>> edges;

	sort(id.begin(), id.end(), [&](int a, int b) {

		return X[a] < X[b];

	});

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

		edges.push_back({min(abs(X[id[i]] - X[id[i + 1]]), abs(Y[id[i]] - Y[id[i + 1]])), {id[i], id[i + 1]}});

	}

	sort(id.begin(), id.end(), [&](int a, int b) {

		return Y[a] < Y[b];

	});

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

		edges.push_back({min(abs(X[id[i]] - X[id[i + 1]]), abs(Y[id[i]] - Y[id[i + 1]])), {id[i], id[i + 1]}});

	}

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

	vector<int> par(n);

	iota(par.begin(), par.end(), 0);

	function<int(int)> getRoot = [&](int a) {

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

		return par[a] = getRoot(par[a]);

	};

	ll ans = 0;

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

		int a, b;

		tie(a, b) = edges[i].second;

		int pa = getRoot(a), pb = getRoot(b);

		if (pa == pb) continue;

		par[pa] = pb;

		ans += edges[i].first;

	}

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

}