# Original solution
# coding: utf-8
import array, bisect, collections, copy, heapq, itertools, math, random, re, string, sys, time
sys.setrecursionlimit(10 ** 7)
INF = 10 ** 20
MOD = 10 ** 9 + 7


def II(): return int(eval(input()))
def ILI(): return list(map(int, input().split()))
def IAI(LINE): return [ILI() for __ in range(LINE)]
def IDI(): return {key: value for key, value in ILI()}


def read():
    N = II()
    x, y = [], []
    for __ in range(N):
        _x, _y = ILI()
        x.append(_x)
        y.append(_y)
    return N, x, y


def solve(N, x, y):
    cost = [[INF] * N for __ in range(N)]
    for i in range(N):
        for j in range(N):
            x_i, y_i = x[i], y[i]
            x_j, y_j = x[j], y[j]
            cost[i][j] = min(abs(x_i - x_j), abs(y_i - y_j))

    min_cost = [INF] * N
    bool_used = [False] * N

    ans = 0
    min_cost[0] = 0
    while True:
        v = -1
        for i in range(N):
            if bool_used[i] is False and (v == -1 or min_cost[i] < min_cost[v]):
                v = i

        if v == -1:
            break
        bool_used[v] = True
        ans += min_cost[v]
        for i in range(N):
            min_cost[i] = min(min_cost[i], cost[v][i])

    return ans


def main():
    params = read()
    print((solve(*params)))


if __name__ == "__main__":
    main()


# Optimized solution
# coding: utf-8
import array, bisect, collections, copy, heapq, itertools, math, random, re, string, sys, time
sys.setrecursionlimit(10 ** 7)
INF = 10 ** 20
MOD = 10 ** 9 + 7


def II(): return int(eval(input()))
def ILI(): return list(map(int, input().split()))
def IAI(LINE): return [ILI() for __ in range(LINE)]
def IDI(): return {key: value for key, value in ILI()}


def read():
    N = II()
    x, y = [], []
    for __ in range(N):
        _x, _y = ILI()
        x.append(_x)
        y.append(_y)
    return N, x, y


class UnionFind(object):
    def __init__(self, number_of_nodes):  # 初期化
        self.par = array.array("L", list(range(number_of_nodes)))
        self.rank = array.array("L", (0 for i in range(number_of_nodes)))

    def root(self, node):  # 根を求める
        if self.par[node] == node:
            return node
        else:
            r = self.root(self.par[node])
            self.par[node] = r  # 経路圧縮
            return r

    def in_the_same_set(self, node1, node2):  # 同じ集合に属するか
        return self.root(node1) == self.root(node2)

    def unite(self, node1, node2):  # 属する集合を併合
        x = self.root(node1)
        y = self.root(node2)
        if x == y:
            pass
        elif self.rank[x] < self.rank[y]:
            self.par[x] = y
        else:
            self.par[y] = x
            if self.rank[x] == self.rank[y]:
                self.rank[x] += 1


def solve(N, x, y):
    edges = []
    for i in range(N):
        for j in range(i + 1, N):
            edges.append((min(abs(x[i] - x[j]), abs(y[i] - y[j])) , i, j))
    
    edges.sort(key=lambda x: x[0])
    union_find = UnionFind(N)
    ans = 0
    for edge in edges:
        if not union_find.in_the_same_set(edge[1], edge[2]):
            union_find.unite(edge[1], edge[2])
            ans += edge[0]
    
    return ans


def main():
    params = read()
    print((solve(*params)))


if __name__ == "__main__":
    main()