# Original solution
import operator
import sys

input = sys.stdin.readline

ri = lambda: int(eval(input()))
rs = lambda: input().rstrip()
ril = lambda: list(map(int, input().split()))
rsl = lambda: input().rstrip().split()
ris = lambda n: [ri() for _ in range(n)]
rss = lambda n: [rs() for _ in range(n)]
rils = lambda n: [ril() for _ in range(n)]
rsls = lambda n: [rsl() for _ in range(n)]


class UnionFind:
    def __init__(self, n):
        self.n = n
        self.parents = list(range(n + 1))
        self.ranks = [0 for _ in range(n + 1)]

    def get_root(self, x):
        if self.parents[x] == x:
            return x
        self.parents[x] = self.get_root(self.parents[x])
        return self.parents[x]

    def merge(self, x, y):
        x = self.get_root(x)
        y = self.get_root(y)
        if x != y:
            if self.ranks[x] < self.ranks[y]:
                self.parents[x] = y
            else:
                self.parents[y] = x
                if self.ranks[x] == self.ranks[y]:
                    self.ranks[x] += 1


def kruskal(n_nodes, edges):
    edges.sort(key=operator.itemgetter(2))
    res = []
    uf = UnionFind(n_nodes)
    for e in edges:
        if uf.get_root(e[0]) != uf.get_root(e[1]):
            res.append(e)
            uf.merge(e[0], e[1])
    return res


n = ri()
ls = rils(n)
ls = list(enumerate(ls))

edges = []
ls.sort(key=lambda x: x[1][0])
for (i, (x0, y0)), (j, (x1, y1)) in zip(ls, ls[1:]):
    edges.append((i, j, min(abs(x0 - x1), abs(y0 - y1))))

ls.sort(key=lambda x: x[1][1])
for (i, (x0, y0)), (j, (x1, y1)) in zip(ls, ls[1:]):
    edges.append((i, j, min(abs(x0 - x1), abs(y0 - y1))))

res = kruskal(n, edges)
print((sum(x[2] for x in res)))

# Optimized solution
import operator
import sys

input = sys.stdin.readline

ri = lambda: int(eval(input()))
rs = lambda: input().rstrip()
ril = lambda: list(map(int, input().split()))
rsl = lambda: input().rstrip().split()
ris = lambda n: [ri() for _ in range(n)]
rss = lambda n: [rs() for _ in range(n)]
rils = lambda n: [ril() for _ in range(n)]
rsls = lambda n: [rsl() for _ in range(n)]


class UnionFind:
    def __init__(self, n):
        self.n = n
        self.parents = list(range(n))
        self.ranks = [0 for _ in range(n)]

    def get_root(self, x):
        if self.parents[x] == x:
            return x
        self.parents[x] = self.get_root(self.parents[x])
        return self.parents[x]

    def merge(self, x, y):
        x = self.get_root(x)
        y = self.get_root(y)
        if x != y:
            if self.ranks[x] < self.ranks[y]:
                self.parents[x] = y
            else:
                self.parents[y] = x
                if self.ranks[x] == self.ranks[y]:
                    self.ranks[x] += 1


def kruskal(n_nodes, edges):
    edges.sort(key=operator.itemgetter(2))
    res = []
    uf = UnionFind(n_nodes)
    for e in edges:
        if uf.get_root(e[0]) != uf.get_root(e[1]):
            res.append(e)
            uf.merge(e[0], e[1])
    return res


n = ri()
ls = rils(n)
ls = list(enumerate(ls))

edges = []
ls.sort(key=lambda x: x[1][0])
for (i, (x0, y0)), (j, (x1, y1)) in zip(ls, ls[1:]):
    edges.append((i, j, min(abs(x0 - x1), abs(y0 - y1))))

ls.sort(key=lambda x: x[1][1])
for (i, (x0, y0)), (j, (x1, y1)) in zip(ls, ls[1:]):
    edges.append((i, j, min(abs(x0 - x1), abs(y0 - y1))))

res = kruskal(n, edges)
print((sum(x[2] for x in res)))