#include <bits/stdc++.h>
using namespace std;
char _buf[11 * 1000000 + 3];
int loadint() {
  fgets(_buf, 11 + 3, stdin);
  return atoi(_buf);
}
int loadvec(vector<int>& v, int N) {
  int bufsize = 11 * N + 3;
  fgets(_buf, bufsize, stdin);
  v.resize(N);
  int i = 0;
  bool last = false;
  for (char* p = &_buf[0];;) {
    char* q = p;
    while (*q > ' ') ++q;
    if (*q == 0x0D || *q == 0x0A) last = true;
    *q = 0;
    v[i++] = atoi(p);
    if (last || i == N) break;
    p = q + 1;
  }
  return i;
}
class UnionFind {
  vector<int> data;

 public:
  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)]; }
};
long long solve(int n, vector<int>& x, vector<int>& y) {
  assert(x.size() == n && y.size() == n);
  vector<bool> vis(n, false);
  multimap<int, int> xx, yy;
  for (int i = 0; i < (n); ++i) {
    xx.insert(pair<int, int>(x[i], i));
    yy.insert(pair<int, int>(y[i], i));
  }
  priority_queue<pair<int, pair<int, int>>> pqx, pqy;
  auto jet =
      [](int i, vector<bool>& vis, vector<int>& x, multimap<int, int>& xx,
         priority_queue<pair<int, pair<int, int>>>& pq, const char* x_y) {
        assert(vis[i]);
        auto ax = xx.equal_range(x[i]);
        for (auto it = ax.first; it != ax.second; ++it) {
          if (it->second != i) continue;
          assert(it != xx.end());
          for (auto a = it;;) {
            int j = a->second;
            if (j != i && !vis[j]) {
              pq.push(make_pair(-abs(x[j] - x[i]), pair<int, int>(i, j)));
              break;
            }
            if (a == xx.begin()) break;
            --a;
          }
          for (auto b = it; b != xx.end(); ++b) {
            int j = b->second;
            if (j != i && !vis[j]) {
              pq.push(make_pair(-abs(x[j] - x[i]), pair<int, int>(i, j)));
              break;
            }
          }
          break;
        }
      };
  vis[0] = true;
  long long cost = 0;
  jet(0, vis, x, xx, pqx, "x");
  jet(0, vis, y, yy, pqy, "y");
  auto get_nearest = [](vector<bool>& vis,
                        priority_queue<pair<int, pair<int, int>>>& pq) -> int {
    while (!pq.empty()) {
      int u = pq.top().second.first, v = pq.top().second.second;
      assert(vis[u]);
      if (vis[v]) {
        pq.pop();
        continue;
      } else {
        return -pq.top().first;
      }
    }
    return 0x7fffffff;
  };
  for (int z = 1; z < n; ++z) {
    int x_nearest = get_nearest(vis, pqx);
    int y_nearest = get_nearest(vis, pqy);
    if (x_nearest == 0x7fffffff && y_nearest == 0x7fffffff) {
      assert(false);
      break;
    }
    auto fn0 = [](vector<bool>& vis,
                  priority_queue<pair<int, pair<int, int>>>& pq) {
      int v = pq.top().second.first, a = pq.top().second.second;
      pq.pop();
      return pair<int, int>(v, a);
    };
    int v, a, d;
    if (x_nearest < y_nearest) {
      pair<int, int> va = fn0(vis, pqx);
      v = va.first;
      a = va.second;
      d = x_nearest;
    } else {
      pair<int, int> va = fn0(vis, pqy);
      v = va.first;
      a = va.second;
      d = y_nearest;
    }
    assert(vis[v] && !vis[a]);
    vis[a] = true;
    cost += d;
    jet(a, vis, x, xx, pqx, "x");
    jet(a, vis, y, yy, pqy, "y");
  }
  return cost;
}
int main() {
  int N = loadint();
  vector<int> tmp(2);
  vector<int> x(N), y(N);
  for (int i = 0; i < (N); ++i) {
    loadvec(tmp, 2);
    x[i] = tmp[0];
    y[i] = tmp[1];
  }
  printf("%lld\n", solve(N, x, y));
  return 0;
}
