// 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.388443545677328x):
#include<bits/stdc++.h>

const int N = 1e5+5;

using namespace std;

int n;

struct Node{

	int x;

	int y;

	int id;

	void show(){

		cout << this->x <<" "<<this->y<<" "<<this->id<<"\n";

	}

}a[N];

bool cmp1(const Node &a, const Node &b){

	if(a.x < b.x) return 1;

	if(a.x == b.x) return a.y < b.y;

	return 0;

}

bool cmp2(const Node &a, const Node &b){

	if(a.y < b.y) return 1;

	if(a.x == b.x) return a.x < b.x;

	return 0;

}

struct cmpp{

	bool operator()(const Node &a, const Node &b){

		if(a.x > b.x) return 1;

		if(a.x == b.x) return a.y > b.y;

		return 0;

	}

};

priority_queue<tuple<int,int,int>, vector<tuple<int,int,int>>, greater<tuple<int,int,int>> > pq;



int counting;

vector<int> par, children;



void Start(int n){

	counting = n;

 	par.assign(n+1,-1);

	children.assign(n+1,1);

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

		par[i] = i;

	}

	return;

}



int Find(int i){

	if(par[i] != i) par[i] = Find(par[i]);

	return par[i];

}



bool Union(int i, int j){

	i = Find(i);

	j = Find(j);

	if(i != j){

		if(children[i] < children[j]){

			par[i] = j;

			children[j] += children[i];	

		}else{

			par[j] = i;

			children[i] += children[j];

		}

		counting--;

	}else return 0;

	return 1;

}



signed main(){

	cin >> n;

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

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

		a[i].id = i; 

		

	}

	

	sort(a+1, a+1+n, cmp1);

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

		if(i!=1) pq.push(make_tuple(abs(a[i].x - a[i-1].x), a[i].id, a[i-1].id));

	}



	sort(a+1, a+1+n, cmp2);

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

		if(i!=1) pq.push(make_tuple(abs(a[i].y - a[i-1].y), a[i].id, a[i-1].id));

	}

	int ans = 0, dist, u, v;

	Start(n);

	while(pq.size()){

		if(counting == 1) break;

		tie(dist, u, v) = pq.top();

		pq.pop();

		if(Union(u, v)){ 

			ans += dist;

		}

	}

	cout << ans <<"\n";

}