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

using namespace std;

#define int long long

vector<pair<int,pair<int,int> > >points;

vector<pair<int,pair<int,int> > > edge;

int par[100005];

bool cmp(pair<int,pair<int,int> > &a,pair<int,pair<int,int> > &b ){

	return a.second.first<b.second.first;

}

bool cmp2(pair<int,pair<int,int> > &a,pair<int,pair<int,int> > &b ){

	return a.second.second<b.second.second;

}

void init(){

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

		par[i]=i;

	}

}

int find(int i){

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

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

}

void dsu(int i,int j){

	par[find(i)]=find(j);

}

bool same(int i,int j){

	return find(i)==find(j);

}

signed main(){

//	freopen("plantree.inp","w",stdin);

//	freopen("plantree.out","r",stdout);

	ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);

	int n;

	cin>>n;

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

		int x,y;

		cin>>x>>y;

		points.push_back(make_pair(i,make_pair(x,y)));

	}	

	init();

	sort(points.begin(),points.end(),cmp);

	for(int i=1;i<points.size();i++){

		edge.push_back(make_pair(points[i].second.first-points[i-1].second.first,make_pair(points[i].first,points[i-1].first)));

	}

	sort(points.begin(),points.end(),cmp2);

	for(int i=1;i<points.size();i++){

		edge.push_back(make_pair(points[i].second.second-points[i-1].second.second,make_pair(points[i].first,points[i-1].first)));

	}

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

	int ans=0;

	

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

		if(!same(edge[i].second.second,edge[i].second.first)){

			ans+=edge[i].first;

			dsu(edge[i].second.second,edge[i].second.first);

		}

	}

	cout<<ans;

}

// Faster C++ solution for the same problem (measured speedup: 1.8360170488061462x):


#include<bits/stdc++.h>

#define LL long long

#define MOD (LL)1000000007

#define pi acos(-1.0)

#define ULL unsigned long long

#define mem_1(str) memset(str,-1,sizeof(str))

#define mem0(str) memset(str,0,sizeof(str))

#define rep(i,a,n) for (int i=a;i<n;i++)

#define per(i,a,n) for (int i=n-1;i>=a;i--)

#define INF 999999999

using namespace std;

struct ee{            //存放每边的起点终点和权值 

	LL x,y;

	int id;

}num[200000];  

LL p[200000];

struct edge{            //存放每边的起点终点和权值 

	LL u,v;

	LL w;

}myedge[500000];  

bool cmp(const edge& p1,const edge& p2)    

{

	 if(p1.w<p2.w)return true;

     else return false;

}

bool cmpp(const ee& p1,const ee& p2)    

{

	 if(p1.x<p2.x)return true;

     else return false;

}

bool cmppp(const ee& p1,const ee& p2)    

{

	 if(p1.y<p2.y)return true;

     else return false;

}

LL findset(LL x)             //寻找根节点并压缩路径 

{

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

	else p[x]=findset(p[x]);

	return p[x];

}

LL kruskal(int n,int m)      //kruskal算法 

{

	LL x,y;

	LL ans=0;

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

	    p[i]=i;

	sort(myedge+1,myedge+m+1,cmp);

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

	{	

		x=findset(myedge[i].u);

		y=findset(myedge[i].v);

		if(x!=y)

		{

			ans+=myedge[i].w; 

			p[y]=x;                                  

		}

	}

	return ans;

}

int main()

{

	int n;

	LL ans; 

	scanf("%d",&n);

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

	{

		scanf("%lld%lld",&num[i].x ,&num[i].y );

		num[i].id =i;

	}

	sort(num+1,num+n+1,cmpp);

	int s=0;

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

	{

		myedge[++s].u =num[i].id ;

		myedge[s].v =num[i+1].id ;

		myedge[s].w =num[i+1].x -num[i].x ;

	}

	sort(num+1,num+n+1,cmppp);

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

	{

		myedge[++s].u =num[i].id ;

		myedge[s].v =num[i+1].id ;

		myedge[s].w =num[i+1].y -num[i].y ;

	}

	ans=kruskal(n,s);

	printf("%lld",ans);

}