void solve();

int main() {
	solve();
	return 0;
}

//////////////////////////////////////////////////
//////////////////////////////////////////////////
#include <iostream>
#include <algorithm>
#include <vector>
#include <set>
#include <queue>
#include <functional>
#include <map>


using namespace std;

typedef pair<int, int> pii;

int N;
class pos {
public:
	int n;
	long int x, y;
	pos(int _n, long int _x, long int _y) :n(_n), x(_x), y(_y) {}
	pos() :n(0),x(0), y(0) {}
};
vector<pos> vs;

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

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;
	}
	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;   //根が同じだから何もせずに帰る
	if (rank[x] < rank[y])p[x] = y;
	else {
		p[y] = x;
		if (rank[x] == rank[y])rank[x]++;
	}
	return;
}

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

int unionFind::size() {
	return N;
}


//重み付きグラフ
//距離の部分をテンプレートに
template<class T>
class wGraph {
public:
	int N;
	vector<multimap<int, T> >* E;
	wGraph(int n) {
		N = n;
		E = new vector<multimap<int, T> >;
		E->resize(N);
	}
	~wGraph() {
		delete E;
	}
	void addEdge(int a, int b, T c) {
		E->at(a).emplace(b, c);
	}
	bool isConnected(int a, int b) {
		return (E->at(a).find(b) != E->at(a).end());
	}
	//最小全域木問題(クラスカル法)
//最小全域木自体と、重み和
//wGraphに追加する感じで
//O( ElogV )
	T minimumSpanningTree() {
		typedef pair<T, pii> ldii;
		priority_queue<ldii, vector<ldii>, greater<ldii> >* q;
		q = new priority_queue<ldii, vector<ldii>, greater<ldii> >;
		for (int i = 0; i < this->N; i++) {
			for (auto itr = this->E->at(i).begin(); itr != this->E->at(i).end(); itr++) {
				q->push(ldii((*itr).second, pii(i, (*itr).first)));
			}
		}
		wGraph<T>* g = new wGraph<T>(this->N);
		unionFind* u = new unionFind(this->N);
		T ans = 0;
		while (!q->empty()) {
			ldii e = q->top();
			q->pop();
			int s = e.second.first, t = e.second.second;
			if (u->parent(s) != u->parent(t)) {
				u->unit(s, t);
				ans += e.first;
			}
		}
		delete u;
		delete g;
		return ans;
	}
};

void solve() {
	cin >> N;
	vs.resize(N);
	for (int n = 0; n < N; n++) {
		long int x, y;
		cin >> x >> y;
		vs[n] = pos(n,x,y);
	}
	wGraph<long int> G(N);
	sort(vs.begin(), vs.end(), [](pos a, pos b) {
		if (a.x != b.x)return a.x < b.x;
		if (a.y != b.y)return a.y < b.y;
		return a.n < b.n;
	});
	for (int i = 0; i < N - 1; i++) {
		G.addEdge(vs[i].n,vs[i+1].n,vs[i+1].x-vs[i].x);
		G.addEdge(vs[i+1].n, vs[i].n, vs[i + 1].x - vs[i].x);
	}
	sort(vs.begin(), vs.end(), [](pos a, pos b) {
		if (a.y != b.y)return a.y < b.y;
		if (a.x != b.x)return a.x < b.x;
		return a.n < b.n;
	});
	for (int i = 0; i < N - 1; i++) {
		G.addEdge(vs[i].n, vs[i + 1].n, vs[i + 1].y - vs[i].y);
		G.addEdge(vs[i + 1].n, vs[i].n, vs[i + 1].y - vs[i].y);
	}
	cout << G.minimumSpanningTree() << endl;
	cin >> N;
}

Measured memory_bytes: 45804