#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long double ld;
typedef pair<int, int> pii;
#define rep(i,n) for (int i=0; i<(n); i++)
#define reps(i,s,n) for (int i=(s); i<(n); i++)
#define rep1(i,n) for (int i=1; i<=(n); i++)
#define repr(i,s,n) for (int i=(s)-1; i>=(n); i--)
#define print(a) cout << (a) << endl
#define all(v) v.begin(), v.end()
#define rsort(v) sort(v.rbegin(), v.rend())

struct UnionFind {
  vector<int> par;
  UnionFind(int n) : par(n) { par.assign(n, -1); }

  int root(int a) {
    if (par[a] < 0)
      return a;
    return par[a] = root(par[a]);
  }
  int size(int a) { return -par[root(a)]; }
  void unite(int a, int b) {
    int ra = root(a), rb = root(b);
    if (ra == rb)
      return;
    if (par[a]>par[b])
      swap(a, b);
    par[ra] += par[rb];
    par[rb] = ra;
    return;
  }
  bool same(int a, int b) {
    int ra = root(a), rb = root(b);
    return ra == rb;
  }
};
UnionFind uft(100001);

struct edge {
  ll cost;
  int n1;
  int n2;
  bool operator<(const edge& right) const {
    return cost<=right.cost;
  }
};

int main() {
  int N;
  cin >> N;
  vector<pair<ll,int>> X(N),Y(N);
  rep(i,N) {
    ll x,y;
    cin >> x >> y;
    X[i] = {x,i};
    Y[i] = {y,i};
  }
  set<edge> S;
  sort(all(X));
  sort(all(Y));
  rep1(i,N-1) {
    S.insert({X[i].first-X[i-1].first, X[i].second, X[i-1].second});
    S.insert({Y[i].first-Y[i-1].first, Y[i].second, Y[i-1].second});
  }
  ll ans = 0;
  while (!S.empty()) {
    auto it = S.begin();
    S.erase(it);
    if (uft.same(it->n1,it->n2)) {
      continue;
    }
    uft.unite(it->n1,it->n2);
    ans += it->cost;
  }
  print(ans);
  return 0;
}
#include <bits/stdc++.h>
#define _overload3(_1, _2, _3, name, ...) name
#define _rep(i, n) repi(i, 0, n)
#define repi(i, a, b) for (ll i = (ll)(a); i < (ll)(b); ++i)
#define rep(...) _overload3(__VA_ARGS__, repi, _rep, )(__VA_ARGS__)
#define ll long long
#define lld long double
#define ALL(x) x.begin(), x.end()
using namespace std;

const double EPS = 1e-3;
const double PI = 3.1415926535897932384626433832795028841971;
const int IINF = 1 << 30;
const ll INF = 1ll << 60;
const ll MOD = 1e9 + 7;

int main()
{
    int n;
    cin >> n;
    vector<pair<ll, int>> x(n), y(n);
    rep(i, n)
    {
        x[i].second = i;
        cin >> x[i].first;
        y[i].second = i;
        cin >> y[i].first;
    }
    sort(ALL(x));
    sort(ALL(y));
    vector<int> xpos(n), ypos(n);
    rep(i, n)
    {
        xpos[x[i].second] = i;
        ypos[y[i].second] = i;
    }
    priority_queue<pair<ll, int>, vector<pair<ll, int>>, greater<pair<ll, int>>> pque;
    pque.push({0, 0});
    ll ans = 0;
    vector<bool> used(n, false);
    while (!pque.empty())
    {
        //       cerr << pque.size() << endl;
        ll cost = pque.top().first;
        int idx = pque.top().second;
        pque.pop();
        if (used[idx])
        {
            continue;
        }
        //cerr << idx << " " << cost << endl;
        used[idx] = true;
        //cerr << xpos[idx] << endl;
        ans += cost;
        if (xpos[idx] > 0 && !used[x[xpos[idx] - 1].second])
        {
            pque.push({llabs(x[xpos[idx]].first - x[xpos[idx] - 1].first), x[xpos[idx] - 1].second});
        }
        if (ypos[idx] > 0 && !used[y[ypos[idx] - 1].second])
        {
            pque.push({llabs(y[ypos[idx]].first - y[ypos[idx] - 1].first), y[ypos[idx] - 1].second});
        }

        if (xpos[idx] + 1 < n && !used[x[xpos[idx] + 1].second])
        {
            pque.push({llabs(x[xpos[idx]].first - x[xpos[idx] + 1].first), x[xpos[idx] + 1].second});
        }
        if (ypos[idx] + 1 < n && !used[y[ypos[idx] + 1].second])
        {
            pque.push({llabs(y[ypos[idx]].first - y[ypos[idx] + 1].first), y[ypos[idx] + 1].second});
        }
    }
    cout << ans << endl;

    return 0;
}