#include <bits/stdc++.h>
using namespace std;
;
const int MOD = 1000000007;
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 {
  long long cost;
  long long from;
  long long to;
  bool operator<(const edge &another) const { return cost > another.cost; };
};
priority_queue<edge> node;
int main() {
  int n;
  cin >> n;
  UnionFind UF(n);
  vector<pair<long long, long long> > x, y;
  for (int i = 0; i < n; i++) {
    long long xx, yy;
    cin >> xx >> yy;
    x.push_back(make_pair(xx, i));
    y.push_back(make_pair(yy, i));
  }
  sort((x).begin(), (x).end());
  sort((y).begin(), (y).end());
  for (int i = 0; i < n - 1; i++) {
    long long xcost = x[i + 1].first - x[i].first;
    long long xfrom = x[i].second;
    long long xto = x[i + 1].second;
    long long ycost = y[i + 1].first - y[i].first;
    long long yfrom = y[i].second;
    long long yto = y[i + 1].second;
    node.push(edge{xcost, xfrom, xto});
    node.push(edge{ycost, yfrom, yto});
  }
  long long ans = 0;
  for (int i = 0; i < n - 1; i++) {
    edge e = node.top();
    node.pop();
    while (UF.findSet(e.from, e.to)) {
      e = node.top();
    }
    ans += e.cost;
    UF.unionSet(e.from, e.to);
  }
  cout << ans << endl;
}
