#include <bits/stdc++.h>
using namespace std;
const int MAX_N = 100010;
struct Edge {
  int u, v, cost;
  bool operator<(const Edge& rhs) const { return cost < rhs.cost; }
} ed[MAX_N * 2];
vector<int> xs, ys;
int x[MAX_N], y[MAX_N], dicx[MAX_N], dicy[MAX_N];
int N, M;
int par[MAX_N], _rank[MAX_N];
void init(int N) {
  for (int i = 1; i <= N; i++) {
    par[i] = i;
    _rank[i] = 0;
  }
}
int find(int x) {
  if (par[x] == x) return x;
  return par[x] = find(par[x]);
}
void unite(int x, int y) {
  x = find(x);
  y = find(y);
  if (x == y) return;
  if (_rank[x] < _rank[y]) {
    par[x] = y;
  } else {
    par[y] = x;
    if (_rank[x] == _rank[y]) _rank[x]++;
  }
}
bool same(int x, int y) { return find(x) == find(y); }
void kruskal() {
  sort(ed, ed + M);
  init(N);
  long long ans = 0;
  for (int i = 0; i < M; i++) {
    Edge& e = ed[i];
    if (!same(e.u, e.v)) {
      unite(e.u, e.v);
      ans += e.cost;
    }
  }
  printf("%lld\n", ans);
}
int main() {
  scanf("%d", &N);
  for (int i = 1; i <= N; i++) {
    scanf("%d%d", x + i, y + i);
    xs.push_back(x[i]);
    ys.push_back(y[i]);
  }
  sort(xs.begin(), xs.end());
  sort(ys.begin(), ys.end());
  xs.erase(unique(xs.begin(), xs.end()), xs.end());
  ys.erase(unique(ys.begin(), ys.end()), ys.end());
  for (int i = 1; i <= N; i++) {
    x[i] = lower_bound(xs.begin(), xs.end(), x[i]) - xs.begin();
    y[i] = lower_bound(ys.begin(), ys.end(), y[i]) - ys.begin();
    dicx[x[i]] = i;
    dicy[y[i]] = i;
  }
  for (int i = 1; i <= N; i++) {
    if (x[i] > 0) ed[M++] = (Edge){i, dicx[x[i] - 1], xs[x[i]] - xs[x[i] - 1]};
    if (y[i] > 0) ed[M++] = (Edge){i, dicy[y[i] - 1], ys[y[i]] - ys[y[i] - 1]};
  }
  kruskal();
  return 0;
}
