/**
 * code generated by JHelper
 * More info: https://github.com/AlexeyDmitriev/JHelper
 * @author champon
 */

#include <iostream>
#include <fstream>
#include <bits/stdc++.h>
#define se cout << "test ok" << endl;
#define sp << " " <<
#define enl "\n"
using namespace std;
using ll=long long;
using ld=long double;
using vi = vector<int>;
using vii = vector<vector<int>>;
using vl = vector<ll>;
using vll = vector<vector<ll>>;
using vlll = vector<vector<vector<ll>>>;
using vc = vector<char>;
using vcc = vector<vector<char>>;
using pi = pair<int, int>;
using pl = pair<ll, ll>;
ll mod = ll(1e9)+7;
ll inf = ll(1e18);
void bl(bool b, ostream& out=cout){ out << (b ? "Yes" : "No") << endl; }
void bl2(bool b, ostream& out=cout){ out << (b ? "YES" : "NO") << endl; }
template<typename T> inline bool chmax(T &a, T b){ if(a<b){a=b; return true;} return false; }
template<typename T> inline bool chmin(T &a, T b){ if(a>b){a=b; return true;} return false; }
int dx[] = {1, 0, -1, 0, 1, -1, 1, -1};
int dy[] = {0, 1, 0, -1, 1, -1, -1, 1};

#ifndef INCLUDE_DEBUG_HPP
#define INCLUDE_DEBUG_HPP

#include <iostream>
#include <vector>
#include <map>
using namespace std;

namespace dbg {
    using ll = long long;

    class Debug {
    public:
        Debug(){}
        template<typename T>
        void vd(vector<T> vec);
        template<typename T>
        void vd2(vector<vector<T>> vec);
        template<typename T>
        void ad(T *arr, ll n);
        template<typename T, size_t N>
        void ad2(T (&arr)[N], ll n);
        template<typename T>
        void md(T mp);
    };

    template<typename T>
    void Debug::vd(vector<T> vec) {
        for (auto vv : vec) cout << vv << " ";
        cout << endl;
    }

    template<typename T>
    void Debug::vd2(vector<vector<T>> vec) {
        for (auto vv : vec) {
            for (auto vvv : vv) cout << vvv << " ";
            cout << endl;
        }
    }

    template<typename T>
    void Debug::ad(T *arr, ll n) {
        for (int i = 0; i <= n; i++) cout << arr[i] << " ";
        cout << endl;
    }

    template<typename T, size_t N>
    void Debug::ad2(T (&arr)[N], ll n) {
        for (int i = 0; i <= N; i++) for (int j = 0; j <= n; j++) cout << arr[i][j] << " ";
        cout << endl;
    }

    template<typename T>
    void Debug::md(T mp) {
        cout << "key : value" << endl;
        for (auto const &m : mp) cout << m.first << " : " << m.second << endl;
        cout << endl;
    }

}

#endif //INCLUDE_DEBUG_HPP

using dbg::Debug;
Debug debug;

//
// Created by champon1020 on 2020/04/11.
//

#ifndef INCLUDE_KRUSKAL_HPP


#include <algorithm>
using namespace std;

namespace kruskal {

    using ll = long long;

    class Kruskal {
        struct edge {
            int u, v;
            ll cost;
            edge(int u, int v, ll cost):u(u), v(v), cost(cost){};
        };

        // >>> simple unionfind
        vector<ll> par;
        void init_uf(int n) {
            par.assign(n, 0);
            for(int i=0; i<n; i++){
                par[i] = i;
            }
        }

        ll find(ll x){
            if(par[x] == x) return x;
            else return par[x] = find(par[x]);
        }

        void unite(ll x, ll y){
            x = find(x);
            y = find(y);
            if(x == y) return;
            par[x] = y;
        }

        bool same(ll x, ll y){
            return find(x) == find(y);
        }
        // <<< unionfind

        static bool comp(const edge& e1, const edge& e2) {
            return e1.cost < e2.cost;
        }

    public:
        vector<edge> es;
        int v, e;   // v: 頂点数, e: 辺数
        Kruskal(int v, int e);
        void add(int e1, int e2, ll cost);
        ll compute();
    };

    Kruskal::Kruskal(int v, int e):v(v),e(e) {}

    void Kruskal::add(int e1, int e2, ll cost) {
        es.emplace_back(e1, e2, cost);
    }

    ll Kruskal::compute() {
        sort(es.begin(), es.end(), comp);
        init_uf(v);
        ll res = 0;
        for(auto ee : es){
            if(!same(ee.u, ee.v)){
                unite(ee.u, ee.v);
                res += ee.cost;
            }
        }
        return res;
    }
}

#define INCLUDE_KRUSKAL_HPP

#endif //INCLUDE_KRUSKAL_HPP


// verify
// https://onlinejudge.u-aizu.ac.jp/courses/library/5/GRL/2/GRL_2_A
using kruskal::Kruskal;

class DBuilt {
public:
    struct Point {
        ll x, y;
        Point(ll x, ll y):x(x),y(y){}
        bool operator<(Point const& rhs) const {
            if(x == rhs.x) return y < rhs.y;
            return x < rhs.x;
        }
    };

    using ppair = pair<Point, int>;

	void solve(std::istream& in, std::ostream& out) {
        int n;
        in >> n;
        ll x, y;
        vector<ppair> ex, ey;
        for(int i=0; i<n; i++){
            in >> x >> y;
            ex.emplace_back(Point(x, y), i);
            ey.emplace_back(Point(y, x), i);
        }

        sort(ex.begin(), ex.end());
        sort(ey.begin(), ey.end());

        Kruskal kr(n, 2*(n-1));
        for(int i=0; i<n-1; i++){
            ll costx = min(abs(ex[i].first.x - ex[i+1].first.x), abs(ex[i].first.y - ex[i+1].first.y));
            ll costy = min(abs(ey[i].first.x - ey[i+1].first.x), abs(ey[i].first.y - ey[i+1].first.y));
            kr.add(ex[i].second, ex[i+1].second, costx);
            kr.add(ey[i].second, ey[i+1].second, costy);
        }

        out << kr.compute() << enl;
	}
};


int main() {
    cin.tie(nullptr);
    ios_base::sync_with_stdio(false);
	DBuilt solver;
	std::istream& in(std::cin);
	std::ostream& out(std::cout);
	solver.solve(in, out);
	return 0;
}


Measured memory_bytes: 13860