// Original C++ solution (slower):
#include "bits/stdc++.h"

using namespace std;

typedef long long ll;

typedef pair<int, int> pii;

typedef pair<ll, ll> pll;

const int INF = 1e9;

const ll LINF = 1e18;



/*

<url:https://arc076.contest.atcoder.jp/tasks/arc076_b>

問題文============================================================

 平面上に、N 個の街があります。i 個目の街は、座標 (xi,yi) にあります。

 同じ座標に、複数の街があるかもしれません。

 

 座標 (a,b) にある街と座標 (c,d) にある街の間に道を造るのには、min(|a−c|,|b−d|) 円かかります。

 街と街の間以外に、道を造ることはできません。

 

 任意の 2 つの街の間を、道を何本か通って行き来できるようにするためは、最低で何円必要でしょうか。



=================================================================



解説=============================================================



================================================================

*/

struct UnionFind {

    vector<int> data;

    UnionFind(int size) : data(size, -1) { }

    bool unionSet(int x, int y) {

        x = root(x); y = root(y);

        if (x != y) {

            if (data[y] < data[x]) swap(x, y);

            data[x] += data[y]; data[y] = x;

        }

        return x != y;

    }

    bool findSet(int x, int y) {

        return root(x) == root(y);

    }

    int root(int x) {

        return data[x] < 0 ? x : data[x] = root(data[x]);

    }

    int size(int x) {

        return -data[root(x)];

    }

};



struct edge{

    ll u,v,cost;

    edge(){}

    edge(ll u,ll v,ll cost):u(u),v(v),cost(cost){}

    bool operator < (const edge& o) const{

        return cost < o.cost;

    }

    bool operator > (const edge& o) const{

        return cost > o.cost;

    }

};



ll solve(){

    ll N; cin >> N;

    vector<pll> p(N);

    for(int i = 0; i < N;i++) cin >> p[i].first >> p[i].second;

    vector<pll> xs(N),ys(N);

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

        xs[i] = {p[i].first,i};

        ys[i] = {p[i].second,i};

    }

    

    sort(xs.begin(),xs.end()); sort(ys.begin(),ys.end());

    UnionFind uf(N);

    ll ret = 0;

    

    priority_queue<edge,vector<edge>,greater<edge>> pq;

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

        pq.push(edge(xs[i].second,xs[i+1].second,xs[i+1].first-xs[i].first));

        pq.push(edge(ys[i].second,ys[i+1].second,ys[i+1].first-ys[i].first));

    }

    

    while(!pq.empty()){

        auto e = pq.top(); pq.pop();

        if(uf.findSet(e.u, e.v)) continue;

        

        ret += e.cost;

        uf.unionSet(e.u, e.v);

    }

    

    return ret;

}

int main(void) {

	cin.tie(0); ios::sync_with_stdio(false);

    cout << solve() << endl;

	return 0;

}


// Optimized solution to the same problem (faster):
#include <stdio.h>

#include <stdlib.h>

#include <algorithm>



// 全局变量

const int N = 100010 , M = N + N;

int x[N],y[N],id[N],n;



typedef struct ufset *UFset;

struct ufset

{

  int *parent;

  int *root;

};

UFset UFinit(int size)

{

  int e;

  UFset U=(UFset)malloc(sizeof *U);

  U->parent=(int*)malloc((size+1)*sizeof(int));

  U->root=(int*)malloc((size+1)*sizeof(int));

  for(e=1; e<=size; e++)

  {

    U->parent[e]=1;

    U->root[e]=1;

  }

  return U;

}

int UFfind(int e,UFset U)

{

  int i,j = e;

  while(!U->root[j]) j = U->parent[j];

  while(j!=e){

    i = U->parent[e];

    U->parent[e]=j;

    e=i;

  }

  return j;

}

int UFunion(int i,int j,UFset U)

{

  if(U->parent[i]<U->parent[j])

  {

    U->parent[j]+=U->parent[i];

    U->root[i]=0;

    U->parent[i]=j;

    return j;

  }

  else

  {

    U->parent[i]+=U->parent[j];

    U->root[j]=0;

    U->parent[j]=i;

    return i;

  }

}



// 记录优化后的边集数

struct Edge

{

  int u, v, cost;

  bool operator <(const Edge&b) const

  {

    return cost < b.cost;

  }

} edge[M];

int tot;

// 按照X轴排序

bool cmpX(int a, int b)

{

  return x[a] < x[b];

}

// 按照Y轴排序

bool cmpY(int a, int b)

{

  return y[a] < y[b];

}

void add(int c, int a, int b)

{

  edge[tot].cost = c;

  edge[tot].u = a;

  edge[tot++].v = b;

}

void Work()

{

    scanf("%d", &n);

  int i;

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

  {

    scanf("%d%d", x + i, y + i);

    id[i] = i;

  }

  std::sort(id + 1 , id + n + 1, cmpX);

  for (i = 2; i <= n; ++i)

    add(x[id[i]] - x[id[i - 1]], id[i], id[i - 1]);

  std::sort(id + 1 , id + n + 1, cmpY);

  for (i = 2; i <= n; ++i)

    add(y[id[i]] - y[id[i - 1]], id[i], id[i - 1]);

  UFset UFS = UFinit(n);



  // 按照花费排序

  std::sort(edge, edge + tot);

  long long totcost = 0;

  for (i = 0; i < tot; ++i)

  {

    int u = edge[i].u, v = edge[i].v;

    u = UFfind(u,UFS), v = UFfind(v,UFS);

    if (u != v)

    {

      UFunion(u,v,UFS);

      totcost += edge[i].cost;

    }

  }

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

}

int main()

{

  Work();

  return 0;

}


// Fastest known solution for this problem: