#include <iostream>
#include <string>
#include <cmath>
#include <algorithm>
//#include <cassert>
#include <vector>
//#include <array>
//#include <set>
//#include <map>
//#include <unordered_set>
#include <unordered_map>
//#include <stack>
#include <queue>
#define REP(i, n) for (int i = 0; i < (int)(n); i++)
#define REP1(i, n) for (int i = 1; i <= (int)(n); i++)
using ll = long long;
using namespace std;

//----------------------------------------------------------

using Weight = long long;

struct Vertex;
using Vertices = std::vector<Vertex *>;
struct Edge;
using Edges = std::vector<const Edge *>;

struct Vertex {
	const int id;
	Edges edges;
	Vertex(int id);
	void add_edge(const Edge *const p_e);
	void add_edge(const Edges &es);
};

struct Edge {
	Vertex *p_src, *p_dst;
	Weight weight;

	Edge(Vertex *p_src, Vertex *p_dst, Weight weight);
	Edge(const Edge &e);
	Edge& operator = (const Edge &de);
};

struct Graph {
	Vertices vertices;
	Edges edges;
	Graph(int nvertices);
	~Graph();
	void add_edge(Edge *p_edge);
	void add_edge(int edge_src, int edge_dst, Weight w);
	//void copy_vertex(int id_original, int id_copy);
};

Vertex::Vertex(int id) : id(id) { }
void Vertex::add_edge(const Edge *const p_e) {
	edges.push_back(p_e);
}
void Vertex::add_edge(const Edges &es) {
	for (const auto &p_e : es) {
		add_edge(p_e);
	}
}

//----------------------------------------------------------

Edge::Edge(Vertex *p_src, Vertex *p_dst, Weight weight) : p_src(p_src), p_dst(p_dst), weight(weight) { }
Edge::Edge(const Edge &e) : Edge(e.p_src, e.p_dst, e.weight) {}
Edge& Edge::operator = (const Edge &e) {
	p_src = e.p_src;
	p_dst = e.p_dst;
	weight = e.weight;
	return *this;
}
bool operator < (const Edge &e1, const Edge &e2) {
	return e1.weight != e2.weight ? e1.weight > e2.weight : // !!INVERSE!!
	e1.p_src != e2.p_src ? e1.p_src->id < e2.p_src->id : e1.p_dst->id < e2.p_dst->id;
}

Graph::Graph(int nvertices) {
	for (int id = 0; id < nvertices; id++) {
		vertices.push_back(new Vertex(id));
	}
}
Graph::~Graph() {
	for (auto &p_vertex : vertices) {
		delete p_vertex;
	}
	for (auto &p_edge : edges) {
		delete p_edge;
	}
}
void Graph::add_edge(Edge *p_edge) {
	(*vertices[p_edge->p_src->id]).add_edge(p_edge);
	edges.push_back(p_edge);
}
void Graph::add_edge(int edge_src, int edge_dst, Weight w) {
	add_edge(new Edge(vertices[edge_src], vertices[edge_dst], w));
}
//void Graph::copy_vertex(int id_original, int id_copy) {
//	vertices[id_copy]->add_edge(vertices[id_original]->edges);
//}



Weight kruskal(const Graph &g);

//----------------------------------------------------------
#include <queue>

#include <vector>

struct UnionFind {
	vector<int> data;
	UnionFind(int size) : data(size, -1) { }
	bool unionSet(int x, int y) {
		x = root(x); y = root(y);
		if (x != y) {
			if (data[y] < data[x]) swap(x, y);
			data[x] += data[y]; data[y] = x;
		}
		return x != y;
	}
	bool findSet(int x, int y) {
		return root(x) == root(y);
	}
	int root(int x) {
		return data[x] < 0 ? x : data[x] = root(data[x]);
	}
	int size(int x) {
		return -data[root(x)];
	}
};

Weight kruskal(const Graph &g) {
	size_t nvertices = g.vertices.size();
	UnionFind uf((int)nvertices);
	priority_queue<Edge> que;
	for (const auto &p_e : g.edges)
		if (p_e->p_src->id < p_e->p_dst->id)
			que.push(*p_e);

	Weight sum = 0;
	for (int i = 0; i < nvertices && !que.empty();)
	{
		Edge tmpe(que.top()); que.pop();
		if (uf.unionSet(tmpe.p_src->id, tmpe.p_dst->id)) {
			sum += tmpe.weight;
			i++;
		}
	}

	return sum;
}
using Pwi = pair<Weight, int>;
int N, x, y;

void solve() {
	Weight ans;

	cin >> N;
	priority_queue<Pwi> qx;
	priority_queue<Pwi> qy;
	REP(id, N) {
		cin >> x >> y;
		qx.push(Pwi(x, id));
		qy.push(Pwi(y, id));
	}
	Graph g(N);
	REP(i, N - 1) {
		Pwi tmppair, nxtpair;
		tmppair = qx.top(); qx.pop();
		nxtpair = qx.top();
		g.add_edge(tmppair.second, nxtpair.second, tmppair.first - nxtpair.first);
		g.add_edge(nxtpair.second, tmppair.second, tmppair.first - nxtpair.first);
		tmppair = qy.top(); qy.pop();
		nxtpair = qy.top();
		g.add_edge(tmppair.second, nxtpair.second, tmppair.first - nxtpair.first);
		g.add_edge(nxtpair.second, tmppair.second, tmppair.first - nxtpair.first);
	}

	ans = kruskal(g);

	cout << ans << endl;
	return;
}

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

Measured memory_bytes: 41568