//#pragma warning(disable:4996)
#include <iostream>
#include <vector>
#include <limits.h>
#include <algorithm>
#include <string>
#include <math.h>
#include <limits.h>
#include <queue>
#include <map>
#include <set>
#include <iomanip>
#include <bitset>
#include <cassert>
#include <random>
#include <functional>
#include <stack>
#include <iomanip>
#include <cassert>
//#include <boost/multiprecision/cpp_int.hpp>
#include <complex>
#include <cstdio>
#include <list>
#include <bitset>
//#include <stdio.h>

//< in.txt > out.txt
using namespace std;
//std::ios::sync_with_stdio(false);
//std::cin.tie(0);
const long long MOD = 1e9 + 7;
const long long INF = 1e18;
typedef long long LL;
typedef long double LD;
//typedef boost::multiprecision::cpp_int bigint;
typedef pair<LL, LL> PLL;
typedef pair<int, int> PI;
typedef pair<LD, LL> pdl;
typedef pair<LD, LD> pdd;
typedef vector<LL> VLL;
typedef vector<VLL> VVLL;
typedef vector<int> VI;
typedef vector<vector<int>> VVI;
typedef unsigned long long ULL;

template<class T>
struct Gedge {
	int src, to;
	T cost;
	int id;
	Gedge(int s, int t, T c, int i = -1) :src(s), to(t), cost(c), id(i) {}
	Gedge(int t, T c) :src(-1), to(t), cost(c), id(-1) {}
};

template<class T>
using WeightedGraph = vector<vector<Gedge<T>>>;
using UnweightedGraph = vector<vector<LL>>;
template<class T>
using Gedges = vector<Gedge<T>>;

template<class T>
struct TNode {
	int parent;
	VI childs;
	T cost;
	int id;
	TNode() :parent(-1), cost(0), id(-1) {};
};
template<class T>
using Tree = vector<TNode<T>>;

//unionFind
class unionFind {
private:
	int* p;   //親配列のポインタ
	int* rank;
	int N;   //要素数
	int* check;   //同値な要素の数
public:
	unionFind(int);   //コンストラクタ
	int parent(int);   //親要素を返す
	void unit(int, int);   //2要素をつなぐ
	int operator[](int);   //parentの省略形
	~unionFind();
	int size(int n);   //頂点nと同値な要素数を返す
};

unionFind::unionFind(int n) {
	N = n;
	p = new int[N];
	rank = new int[N];
	for (int i = 0; i < N; i++) {
		p[i] = i;
		rank[i] = 0;
	}
	check = new int[N];
	for (int n = 0; n < N; n++)check[n] = 1;
	return;
}

int unionFind::parent(int n) {
	if (n < 0 || n >= N)return -1;
	if (p[n] == n)return n;   //自分が一番上の親
	return p[n] = parent(p[n]);   //つなぎ直しと上にたどる操作
}

int unionFind::operator[](int n) {
	return parent(n);
}

void unionFind::unit(int x, int y) {
	x = parent(x), y = parent(y);
	if (x == y)return;   //根が同じだから何もせずに帰る
	int sum = check[x] + check[y];
	if (rank[x] < rank[y])p[x] = y;
	else {
		p[y] = x;
		if (rank[x] == rank[y])rank[x]++;
	}
	check[x] = sum;
	check[y] = sum;
	return;
}

unionFind::~unionFind() {
	delete(p);
	delete(rank);
	delete(check);
	return;
}

int unionFind::size(int n) {
	return check[parent(n)];
}

template<class Type>
Type MinSpanTree(WeightedGraph<Type>& G, WeightedGraph<Type>& G2) {
	int N = G.size();
	G2.resize(N);
	unionFind UF(N);
	Gedges<Type> edges;
	for (int n = 0; n < N; n++) {
		for (Gedge<Type>& e : G[n]) {
			edges.push_back(e);
		}
	}
	sort(edges.begin(), edges.end(), [](Gedge<Type>& a, Gedge<Type>& b) {
		return a.cost < b.cost;
	});
	Type ans = 0;
	for (Gedge<Type>& e : edges) {
		int from = e.src;
		int to = e.to;
		if (UF[from] == UF[to])continue;
		ans += e.cost;
		G2[from].push_back({ from,to,e.cost,e.id });
		G2[to].push_back({ to,from,e.cost,e.id });
		UF.unit(from, to);
	}
	return ans;
}

struct point {
	int x, y;
	int n;
	point():x(0),y(0),n(0){}
};

int main() {
	std::cin.tie(0);
	std::ios::sync_with_stdio(false);
	int N;
	cin >> N;
	vector<point> points(N);
	for (int n = 0; n < N; n++) {
		cin >> points[n].x >> points[n].y;
		points[n].n = n;
	}
	WeightedGraph<LL> G(N);
	sort(points.begin(), points.end(), [](point a,point b) {
		if (a.x != b.x)return a.x < b.x;
		return a.y < b.y;
	});
	for (int n = 0; n < N; n++) {
		if (n > 0) {
			G[points[n].n].push_back(
				{points[n].n,points[n - 1].n,points[n].x - points[n - 1].x });
		}
		if (n < N - 1) {
			G[points[n].n].push_back(
				{points[n].n, points[n + 1].n,points[n + 1].x - points[n].x });
		}
	}
	sort(points.begin(), points.end(), [](point a, point b) {
		if (a.y != b.y)return a.y < b.y;
		return a.x < b.x;
	});
	for (int n = 0; n < N; n++) {
		if (n > 0) {
			G[points[n].n].push_back(
				{ points[n].n,points[n - 1].n,points[n].y - points[n - 1].y });
		}
		if (n < N - 1) {
			G[points[n].n].push_back(
				{ points[n].n,points[n + 1].n,points[n + 1].y - points[n].y });
		}
	}
	WeightedGraph<LL> G2;
	MinSpanTree(G, G2);
	LL ans = 0;
	for (int n = 0; n < N; n++) {
		for (auto& e : G2[n]) {
			ans += e.cost;
		}
	}
	cout << ans / 2 << "\n";
	return 0;
}

Measured memory_bytes: 37596