#include <memory.h>

#include <algorithm>
#include <bitset>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <deque>
#include <iomanip>
#include <iostream>
#include <list>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <utility>
#include <vector>

using namespace std;

#define MOD 1000000007
#define INIT -1

class UF {
  private:
	vector<int> root;
	vector<int> nodenum;

  public:
	UF(int n) {
		root = vector<int>(n, -1);
		nodenum = vector<int>(n, 1);
	}
	int getRoot(int x) {
		if (root[x] == -1) return x;
		return root[x] = getRoot(root[x]);
	}
	int getNodeNum(int x) { return nodenum[getRoot(x)]; }
	void connect(int x, int y) {
		x = getRoot(x);
		y = getRoot(y);
		if (x == y) return;
		if (x > y) swap(x, y);
		root[y] = x;
		nodenum[x] += nodenum[y];
	}
};

int main() {
	int n;
	cin >> n;
	map<int, vector<int> > x;
	map<int, vector<int> > y;
	for (int i = 0; i < n; i++) {
		int tmpx, tmpy;
		cin >> tmpx >> tmpy;
		if (x.find(tmpx) == x.end()) x[tmpx] = vector<int>();
		x[tmpx].push_back(i);
		if (y.find(tmpy) == y.end()) y[tmpy] = vector<int>();
		y[tmpy].push_back(i);
	}
	UF uf(n);
	vector<pair<int, int> > vx, vy;
	for (auto itr = x.begin(); itr != x.end(); itr++) {
		for (int i = 1; i < (*itr).second.size(); i++) {
			uf.connect((*itr).second[0], (*itr).second[i]);
		}
		auto nextitr = itr;
		nextitr++;
		if (nextitr == x.end()) continue;
		vx.push_back(make_pair((*nextitr).first - (*itr).first, (*itr).first));
	}
	for (auto itr = y.begin(); itr != y.end(); itr++) {
		for (int i = 1; i < (*itr).second.size(); i++) {
			uf.connect((*itr).second[0], (*itr).second[i]);
		}
		auto nextitr = itr;
		nextitr++;
		if (nextitr == y.end()) continue;
		vy.push_back(make_pair((*nextitr).first - (*itr).first, (*itr).first));
	}
	sort(vx.begin(), vx.end());
	sort(vy.begin(), vy.end());
	int idxx = 0, idxy = 0;
	long long int ans = 0;
	while (idxx < vx.size() || idxy < vy.size()) {
		if (idxx == vx.size() ||
		    (idxy < vy.size() && vy[idxy].first <= vx[idxx].first)) {
			int tmp = vy[idxy].second;
			auto itr = y.find(tmp);
			itr++;
			int nexttmp = (*itr).first;
			for (int i = 0; i < y[tmp].size(); i++) {
				if (uf.getRoot(y[tmp][i]) == uf.getRoot(y[nexttmp][0]))
					continue;
				uf.connect(y[tmp][i], y[nexttmp][0]);
				ans += vy[idxy].first;
			}
			for (int i = 0; i < y[nexttmp].size(); i++) {
				if (uf.getRoot(y[nexttmp][i]) == uf.getRoot(y[tmp][0]))
					continue;
				uf.connect(y[tmp][0], y[nexttmp][i]);
				ans += vy[idxy].first;
			}
			idxy++;
		} else {
			int tmp = vx[idxx].second;
			auto itr = x.find(tmp);
			itr++;
			int nexttmp = (*itr).first;
			for (int i = 0; i < x[tmp].size(); i++) {
				if (uf.getRoot(x[tmp][i]) == uf.getRoot(x[nexttmp][0]))
					continue;
				uf.connect(x[tmp][i], x[nexttmp][0]);
				ans += vx[idxx].first;
			}
			for (int i = 0; i < x[nexttmp].size(); i++) {
				if (uf.getRoot(x[nexttmp][i]) == uf.getRoot(x[tmp][0]))
					continue;
				uf.connect(x[tmp][0], x[nexttmp][i]);
				ans += vx[idxx].first;
			}
			idxx++;
		}
		// cout << idxx << " " << idxy << endl;
	}
	cout << ans << endl;
}

Measured memory_bytes: 26612