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

#include<cstring>

#include<algorithm>

#include<queue>

#include<cmath>

#include<iostream>

using namespace std;

const int inf=0x3f3f3f3f;

const int maxn=1e5+10;



struct edge{

    int u,v,w;

    edge(int _u=0,int _v=0,int _w=0):u(_u),v(_v),w(_w){

    }

    bool operator<(const edge & a)const{

        return w<a.w;

    }

}es[2*maxn];



struct point{

    int x,y,id;

    point(int _x=0,int _y=0,int _id=0):x(_x),y(_y),id(_id){}

} ps[maxn];



int n,cnt,f[maxn];



bool cmpx(point a,point b){

    return a.x<b.x;

}



bool cmpy(point a,point b){

    return a.y<b.y;

}



int findf(int a){

    return ((f[a]==-1)?a:f[a]=findf(f[a]));

}



int kruskal(){

    int i,ans=0,cc=0;

    memset(f,0xff,sizeof(f));

    sort(es,es+cnt);

    for(i=0;i<cnt;i++){

        int u=es[i].u,v=es[i].v,w=es[i].w;

        int fu=findf(u),fv=findf(v);

        if(fu!=fv){

            ans+=w,++cc;

            f[fu]=fv;

        }

        if(cc==n-1)break;

    }

    if(cc<n-1)return -1;

    return ans;

}

int main(){

    int i,j,k,c,un,vn;

    scanf("%d",&n);

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

        scanf("%d%d",&ps[i].x,&ps[i].y);

        ps[i].id=i;

    }

    sort(ps+1,ps+n+1,cmpx);

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

        es[cnt++]=edge(ps[i].id,ps[i+1].id,(ps[i+1].x-ps[i].x));

    }

    sort(ps+1,ps+n+1,cmpy);

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

        es[cnt++]=edge(ps[i].id,ps[i+1].id,(ps[i+1].y-ps[i].y));

    }

    printf("%d\n",kruskal());

    return 0;

}


// Faster C++ solution for the same problem (measured speedup: 5.02217835985462x):
#include <iostream>

#include <vector>

#include <algorithm>

#include <math.h>

using namespace std;



#define int long long

const int N = 1e5+5;

int n, ans = 0, par[N];



struct point

{

    int x,y,id;

};



struct edge

{

    int u,v,w;

};



bool cmp_x(point a, point b)

{

    return a.x < b.x;

}



bool cmp_y(point a, point b)

{

    return a.y < b.y;

}



bool cmp(edge a, edge b)

{

    return a.w < b.w;

}

int dist(point a, point b)

{

    return min(abs(a.x-b.x),abs(a.y-b.y));

}



void init()

{

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

        par[i] = i;

}



int findSet(int i)

{

    if (i == par[i])

        return i;

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

}



bool isSameSet(int i, int j)

{

    return (findSet(i) == findSet(j));

}



void unionSet(int i, int j)

{

    if (!isSameSet(i,j))

    {

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

    }

}



point tmp_x[N], tmp_y[N];

vector<edge> ve;



signed main()

{

    int x,y;

    cin >> n;

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

    {

        cin >> x >> y;

        tmp_x[i] = tmp_y[i] = {x,y};

        tmp_x[i].id = i;

        tmp_y[i].id = i;

    }

    sort(tmp_x,tmp_x+n,cmp_x);

    sort(tmp_y,tmp_y+n,cmp_y);

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

    {

        ve.push_back({tmp_x[i].id, tmp_x[i+1].id, dist(tmp_x[i],tmp_x[i+1])});

        ve.push_back({tmp_y[i].id, tmp_y[i+1].id, dist(tmp_y[i],tmp_y[i+1])});

    }

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

    init();

    for (auto e: ve)

    {

        int u = e.u, v = e.v, w = e.w;

        if (!isSameSet(u,v))

        {

            unionSet(u,v);

            ans += w;

        }

    }

    cout << ans;

}