#include <algorithm>
#include <bitset>
#include <cassert>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstdlib>
#include <deque>
#include <functional>
#include <iostream>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <stack>
#include <vector>
#define Rep(i, n) for(int i=0;i<n;++i)
#define rep(i, n) for(int i=1;i<=n;++i)
#define ll long long int
#define INF 1e9
#define LINF 1e18
#define MOD 1000000007
#define PI 3.14159265359
#define eps 1e-10
#define All(a) (a).begin(), (a).end()

using namespace std;
using P = pair<ll, ll>;
 
int dx[4] = {0, 1, 0, -1};
int dy[4] = {1, 0, -1, 0};

/**
 * Usage:
 * 
 * G[from].push_back(Edge(to, weight));
 * using Graph = vector<vector<Edge>>;
 * 
 */ 
struct Edge {
  int to;     
  ll weight; 
  Edge(int t, ll w) : to(t), weight(w) { }
};

template<typename T>
void printv(vector<T>& v) {
  if (v.size() == 0) {
    cout << "\n";
    return;
  }

  Rep(i, v.size()) {
    cout << v[i] << ((i + 1 < v.size()) ? ' ' : '\n');
  }
}



int N;
vector<P> x_pos;
vector<P> y_pos;
vector<pair<ll, P>> x_diff_pos;
vector<pair<ll, P>> y_diff_pos;

struct UnionFind {
  vector<int> data;

  // 宣言するときは UnionFind(N+1); でやってください！！！
  UnionFind(int sz) {
    data.assign(sz, -1);
  }

  bool unite(int x, int y) {
    x = find(x); y = find(y); 
    if (x == y) return false;
    if (data[x] > data[y]) swap(x, y);
    data[x] += data[y];
    data[y] = x;
    return true;
  }
  
  bool same(int x, int y) {
    x = find(x); y = find(y); 
    return (x == y);
  }

  int find(int k) {
    if (data[k] < 0) return (k);
    return (data[k] = find(data[k]));
  }

  // 要素 k が属する集合の要素の数を求める
  int size(int k) {
    return -data[find(k)];
  }
};

int main () {
  cin >> N;

  rep(i, N) {
    ll x, y;
    cin >> x >> y;
    x_pos.emplace_back(x, i);
    y_pos.emplace_back(y, i);
  }

  sort(All(x_pos), [](P& x, P& y){ return x.first < y.first; });
  sort(All(y_pos), [](P& x, P& y){ return x.first < y.first; });

  Rep(i, N-1) {
    P a = x_pos[i];
    P b = x_pos[i+1];

    x_diff_pos.emplace_back(b.first - a.first, make_pair(a.second, b.second));

    a = y_pos[i];
    b = y_pos[i+1];

    y_diff_pos.emplace_back(b.first - a.first, make_pair(a.second, b.second));
  }

  sort(All(x_diff_pos), [](pair<ll, P>& x, pair<ll, P>& y){ return x.first < y.first; });
  sort(All(y_diff_pos), [](pair<ll, P>& x, pair<ll, P>& y){ return x.first < y.first; });


  //Rep(i, N-1) {
  //  cout << x_diff_pos[i].first << " " << x_diff_pos[i].second.first << " " << x_diff_pos[i].second.second << "\n";
  //}
  //Rep(i, N-1) {
  //  cout << y_diff_pos[i].first << " " << y_diff_pos[i].second.first << " " << y_diff_pos[i].second.second << "\n";
  //}


  UnionFind uni(N+1);

  int x_tmp = 0;
  int y_tmp = 0;
  int x_ct = 0;
  int y_ct = 0;

  ll ans = 0;

  while (true) {
    if (x_ct + y_ct == N-1) {
      break;
    }

    ll x_dis = x_diff_pos[x_tmp].first;
    ll y_dis = y_diff_pos[y_tmp].first;

    //cout << x_dis << y_dis << "\n";

    if (x_dis < y_dis) {
      if (!uni.same(x_diff_pos[x_tmp].second.first, x_diff_pos[x_tmp].second.second)) {
        uni.unite(x_diff_pos[x_tmp].second.first, x_diff_pos[x_tmp].second.second);
        x_ct++;
        ans += x_dis;
      }

      x_tmp++;
    } else {
      if (!uni.same(y_diff_pos[y_tmp].second.first, y_diff_pos[y_tmp].second.second)) {
        uni.unite(y_diff_pos[y_tmp].second.first, y_diff_pos[y_tmp].second.second);
        y_ct++;
        ans += y_dis;
      }

      y_tmp++;
    }

    //cout << x_tmp << y_tmp << "\n";
    //cout << "\n";
  }


  cout << ans << "\n";
}

Measured memory_bytes: 9568