#include <stdio.h>
#include <stdlib.h>

typedef struct {
	int key, id[2];
} data;

void merge_sort(data x[], int n)
{
	static data y[100001] = {};
	if (n <= 1) return;
	merge_sort(&(x[0]), n/2);
	merge_sort(&(x[n/2]), (n+1)/2);
	
	int i, p, q;
	for (i = 0, p = 0, q = n/2; i < n; i++) {
		if (p >= n/2) y[i] = x[q++];
		else if (q >= n) y[i] = x[p++];
		else y[i] = (x[p].key < x[q].key)? x[p++]: x[q++];
	}
	for (i = 0; i < n; i++) x[i] = y[i];
}

typedef struct {
	data obj[200001];
	int size;
} min_heap;

void push(data x, min_heap* h)
{
	int i = h->size;
	data tmp;
	h->obj[(h->size)++] = x;
	while (1) {
		if (i == 0) break;
		else if (h->obj[i].key < h->obj[(i-1)/2].key) {
			tmp = h->obj[(i-1)/2];
			h->obj[(i-1)/2] = h->obj[i];
			h->obj[i] = tmp;
			i = (i - 1) / 2;
		} else break;
	}
}

data pop(min_heap* h)
{
	int i = 0, j;
	data output = h->obj[0], tmp;
	h->obj[0] = h->obj[--(h->size)];
	while (1) {
		if (i * 2 + 1 >= h->size) break;
		else if (i * 2 + 2 >= h->size) j = i * 2 + 1;
		else if (h->obj[i*2+1].key < h->obj[i*2+2].key) j = i * 2 + 1;
		else j = i * 2 + 2;
		if (h->obj[j].key < h->obj[i].key) {
			tmp = h->obj[j];
			h->obj[j] = h->obj[i];
			h->obj[i] = tmp;
			i = j;
		} else break;
	}
	return output;
}


typedef struct {
	int *par, *size, *height;
} UF_forest;

void UF_initialize(UF_forest *F, int n)
{
	int i;
	F->par = (int*)malloc(sizeof(int) * (n + 1));
	F->size = (int*)malloc(sizeof(int) * (n + 1));
	F->height = (int*)malloc(sizeof(int) * (n + 1));
	for (i = 1; i <= n; i++) {
		F->par[i] = i;
		F->size[i] = 1;
		F->height[i] = 1;
	}
}

int UF_merge(UF_forest *F, int u, int v)
{
	for (; F->par[u] != u; u = F->par[u]);
	for (; F->par[v] != v; v = F->par[v]);
	if (u == v) return -1;
	else if (F->height[u] > F->height[v]) {
		F->par[v] = u;
		F->size[u] += F->size[v];
		return F->size[u];
	} else {
		F->par[u] = v;
		F->size[v] += F->size[u];
		if (F->height[u] == F->height[v]) F->height[v]++;
		return F->size[v];
	}
}

int UF_root(UF_forest *F, int v)
{
	for (; F->par[v] != v; v = F->par[v]);
	return v;
}

int UF_size(UF_forest *F, int v)
{
	for (; F->par[v] != v; v = F->par[v]);
	return F->size[v];
}

int main()
{
	int i, N, x[100001], y[100001];
	scanf("%d", &N);
	for (i = 1; i <= N; i++) scanf("%d %d", &(x[i]), &(y[i]));
	
	data d[100001], e;
	min_heap h;
	h.size = 0;
	UF_forest F;
	UF_initialize(&F, N);
	
	for (i = 0; i < N; i++) {
		d[i].key = x[i+1];
		d[i].id[0] = i + 1;
	}
	merge_sort(d, N);
	for (i = 1; i < N; i++) {
		if (d[i].key == d[i-1].key) UF_merge(&F, d[i].id[0], d[i-1].id[0]);
		else {
			e.key = d[i].key - d[i-1].key;
			e.id[0] = d[i].id[0];
			e.id[1] = d[i-1].id[0];
			push(e, &h);
		}
	}
	
	for (i = 0; i < N; i++) {
		d[i].key = y[i+1];
		d[i].id[0] = i + 1;
	}
	merge_sort(d, N);
	for (i = 1; i < N; i++) {
		if (d[i].key == d[i-1].key) UF_merge(&F, d[i].id[0], d[i-1].id[0]);
		else {
			e.key = d[i].key - d[i-1].key;
			e.id[0] = d[i].id[0];
			e.id[1] = d[i-1].id[0];
			push(e, &h);
		}
	}
	
	int tmp;
	long long ans = 0;
	if (UF_size(&F, 1) == N) printf("0\n");
	else {
		while (h.size > 0) {
			e = pop(&h);
			tmp = UF_merge(&F, e.id[0], e.id[1]);
			if (tmp > 0) {
				ans += e.key;
				if (tmp == N) break;
			}
		}
		printf("%lld\n", ans);
	}
	fflush(stdout);
	return 0;
}

Measured memory_bytes: 8356