#include <bits/stdc++.h>
using namespace std;
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 {
  int src, dst;
  int weight;
  Edge(int src, int dst, int weight) : src(src), dst(dst), weight(weight) {}
};
bool operator<(const Edge &e, const Edge &f) {
  return e.weight != f.weight ? e.weight > f.weight
         : e.src != f.src     ? e.src < f.src
                              : e.dst < f.dst;
}
pair<int, vector<Edge> > minimumSpanningForest(const vector<vector<Edge> > &g) {
  int n = g.size();
  UnionFind uf(n);
  priority_queue<Edge> Q;
  for (int u = 0; u < (int)n; ++u)
    for (__typeof((g[u]).begin()) e = (g[u]).begin(); e != (g[u]).end(); ++e)
      if (u < e->dst) Q.push(*e);
  int total = 0;
  vector<Edge> F;
  while (F.size() < n - 1 && !Q.empty()) {
    Edge e = Q.top();
    Q.pop();
    if (uf.unionSet(e.src, e.dst)) {
      F.push_back(e);
      total += e.weight;
    }
  }
  return pair<int, vector<Edge> >(total, F);
}
int N;
int x[100010], y[100010];
int main() {
  cin >> N;
  for (int i = 0; i < N; i++) {
    cin >> x[i] >> y[i];
  }
  vector<vector<Edge> > g(N);
  for (int i = 0; i < N; i++) {
    for (int j = i + 1; j < N; j++) {
      int w = min(abs(x[i] - x[j]), abs(y[i] - y[j]));
      g[i].push_back(Edge(i, j, w));
      g[j].push_back(Edge(j, i, w));
    }
  }
  pair<int, vector<Edge> > ans = minimumSpanningForest(g);
  cout << ans.first << endl;
  return 0;
}
