#include <iostream>
#include <sstream>
#include <algorithm>
#include <functional>
#include <iterator>
#include <bitset>
#include <string>
#include <list>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>

typedef   signed long long int slli;
typedef unsigned long long int ulli;
const slli MAX_SLLI = 0x7FFFFFFFFFFFFFFF;
const slli MIN_SLLI = 0x8000000000000000;
const ulli MAX_ULLI = 0xFFFFFFFFFFFFFFFF;
const ulli MIN_ULLI = 0x0000000000000000;

#define N_TIMES(i, n)     for (ulli i = 0;     i <  n; ++i)
#define N_TIMES_REV(i, n) for (slli i = n - 1; i >= 0; --i)

#ifdef __DEBUG__
template<typename T>
std::ostream& operator<<(std::ostream &os, const std::list<T> &list)
{
  const std::string delim = ", ";
  typename std::list<T>::const_iterator itr = list.begin();
  while (itr != list.end()) {
    os << *itr;
    ++itr;
    if(itr != list.end()) os << delim;
  }
  return os;
}

template<typename T>
std::ostream& operator<<(std::ostream &os, const std::vector<T> &v)
{
  const std::string delim = ", ";
  for (unsigned n = 0; n < v.size(); ++n) {
    os << v[n];
    if((n + 1) < v.size()) os << delim;
  }
  return os;
}
#endif

struct Point
{
  slli x, y;
  Point(slli x = 0, slli y = 0) : x(x), y(y) {}
  bool operator<(const Point &rhs) const
  {
    return y == rhs.y ? x < rhs.x : y < rhs.y;
  }
};

std::istream& operator>>(std::istream &is, Point &p)
{
  is >> p.x >> p.y;
  return is;
}

inline slli costs(const Point &p, const Point &q) {
  return std::min(::abs(p.x - q.x), ::abs(p.y - q.y));
}

struct PointSortItem
{
  Point p;
  unsigned n;
  PointSortItem(const Point &p, unsigned n)
    : p(p), n(n) {}
};

bool pointSortByLessX(const PointSortItem &lhs, const PointSortItem &rhs)
{
  return lhs.p.x == rhs.p.x ? lhs.n < rhs.n : lhs.p.x < rhs.p.x;
}

bool pointSortByLessY(const PointSortItem &lhs, const PointSortItem &rhs)
{
  return lhs.p.y == rhs.p.y ? lhs.n < rhs.n : lhs.p.y < rhs.p.y;
}

typedef std::pair<unsigned, unsigned> Edge;

void buildEdgeMap(const std::vector<Point> &p, std::map<Edge, ulli> &edge)
{
  unsigned N = p.size();
  
  std::vector<PointSortItem> px, py;
  
  for (unsigned n = 0; n < N; ++n) {
    px.emplace_back(p[n], n);
    py.emplace_back(p[n], n);
  }
  
  std::sort(px.begin(), px.end(), pointSortByLessX);
  std::sort(py.begin(), py.end(), pointSortByLessY);
    
  for (unsigned n = 1; n < N; ++n) {
    edge.emplace(Edge(px[n - 1].n, px[n].n), costs(px[n - 1].p, px[n].p));
    edge.emplace(Edge(py[n - 1].n, py[n].n), costs(py[n - 1].p, py[n].p));
  }
}

class UnionFind
{
private:
  std::vector<unsigned> root, rank;

public:
  UnionFind(unsigned N)
  {
    root = std::vector<unsigned>(N);
    for (unsigned n = 0; n < N; ++n) root[n] = n;
    rank = std::vector<unsigned>(N, 0);
  }
  
  unsigned doFind(unsigned x)
  {
    if (root[x] == x) {
      return x;
    }
    
    root[x] = doFind(root[x]);
    
    return root[x];
  }
  
  void doUnion(unsigned x, unsigned y)
  {
    unsigned x_root = doFind(x), y_root = doFind(y);
    
    if (rank[x_root] > rank[y_root]) {
      root[y_root] = x_root;
    } else if (rank[x_root] < rank[y_root]) {
      root[x_root] = y_root;
    } else if (x_root != y_root) {
      root[y_root] = x_root;
      ++rank[x_root]; 
    }
  }
};

struct SetItem {
  Edge edge;
  unsigned cost;
  
  SetItem(const Edge &edge, unsigned cost) : edge(edge), cost(cost) {}
  
  bool operator<(const SetItem &rhs) const {
    return cost < rhs.cost;
  }
};

ulli searchByKruskal(unsigned N, std::map<Edge, ulli> &edge)
{
  UnionFind forest(N);
  
  std::multiset<SetItem> s;
  
  for (const std::pair<Edge, ulli> &e : edge) {
    s.emplace(e.first, e.second);
  }
  
  unsigned cost = 0;
  
  while (!s.empty()) {
    SetItem item = *s.begin(); s.erase(s.begin());
    
    unsigned  left_tree = forest.doFind(item.edge.first );
    unsigned right_tree = forest.doFind(item.edge.second);
    if (left_tree != right_tree) {
      forest.doUnion(left_tree, right_tree);
      cost += item.cost;
    }
  }
  
  return cost;
}

int main()
{
  unsigned N;
  std::cin >> N;
  
  std::vector<Point> p(N);
  for (unsigned n = 0; n < N; ++n) {
    std::cin >> p[n];
  }
  
  std::map<Edge, ulli> edge;
  buildEdgeMap(p, edge);
  
  std::cout << searchByKruskal(N, edge) << std::endl;
  
  return 0;
}

Measured memory_bytes: 27640