import sys

from heapq import heappush, heappop

buf = sys.stdin.buffer





def main():

    n = int(buf.readline())

    XY = list(map(int, buf.read().split()))

    Xs = []

    Ys = []

    for i, (x, y) in enumerate(zip(XY, XY)):

        Xs.append((x-1, i))

        Ys.append((y-1, i))



    Xs.sort()

    Ys.sort()



    edges = [[] for _ in range(n)]

    for i, ((x, node), (nx, new_node)) in enumerate(zip(Xs[:-1], Xs[1:])):

        edges[node].append((nx-x, new_node))

        edges[new_node].append((nx-x, node))



    for i, ((y, node), (ny, new_node)) in enumerate(zip(Ys[:-1], Ys[1:])):

        edges[node].append((ny-y, new_node))

        edges[new_node].append((ny-y, node))



    seen = [False] * n

    dist = [float('INF')] * n

    todo = [(0, 0)]



    while todo:

        d, node = heappop(todo)

        if seen[node]:

            continue

        seen[node] = True

        dist[node] = d



        while edges[node]:

            edge = edges[node].pop()

            nd, to = edge

            if dist[to] <= nd:

                continue

            heappush(todo, (nd, to))



    print((sum(dist)))





if __name__ == "__main__":

    main()

import sys

buf = sys.stdin.buffer





class UnionFind:

    def __init__(self, num_of_node):

        self.roots = [-1] * num_of_node

        self.ranks = [1] * num_of_node

        self.groups = num_of_node



    def get_root(self, node):

        root = self.roots[node]

        if root == -1:

            return node



        else:

            root = self.get_root(root)

            self.roots[node] = root

            return root



    def is_same_group(self, node1, node2):

        return self.get_root(node1) == self.get_root(node2)



    def unite(self, node1, node2):

        self.groups -= 1

        root1, root2 = self.get_root(node1), self.get_root(node2)

        rank1, rank2 = self.ranks[root1], self.ranks[root2]

        if rank1 < rank2:

            root1, root2 = root2, root1



        self.roots[root2] = root1

        self.ranks[root2] += self.ranks[root1]





def main():

    n = int(buf.readline())

    XY = list(map(int, buf.read().split()))

    Xs = []

    Ys = []

    for i, (x, y) in enumerate(zip(XY, XY)):

        Xs.append((x-1, i))

        Ys.append((y-1, i))



    Xs.sort()

    Ys.sort()



    edges = []

    for i, ((x, node), (nx, new_node)) in enumerate(zip(Xs[:-1], Xs[1:])):

        edges.append((nx-x, node, new_node))



    for i, ((y, node), (ny, new_node)) in enumerate(zip(Ys[:-1], Ys[1:])):

        edges.append((ny-y, node, new_node))



    edges.sort(reverse=True)



    ans = 0

    uf = UnionFind(n)

    while uf.groups != 1:

        d, node1, node2 = edges.pop()

        if uf.is_same_group(node1, node2):

            continue

        uf.unite(node1, node2)

        ans += d



    print(ans)





if __name__ == "__main__":

    main()
import sys
from heapq import heappush, heappop

buf = sys.stdin.buffer


def main():
    n = int(buf.readline())
    XY = list(map(int, buf.read().split()))
    Xs = []
    Ys = []
    for i, (x, y) in enumerate(zip(XY, XY)):
        Xs.append((x - 1, i))
        Ys.append((y - 1, i))
    Xs.sort()
    Ys.sort()
    edges = [[] for _ in range(n)]
    for i, ((x, node), (nx, new_node)) in enumerate(zip(Xs[:-1], Xs[1:])):
        edges[node].append((nx - x, new_node))
        edges[new_node].append((nx - x, node))
    for i, ((y, node), (ny, new_node)) in enumerate(zip(Ys[:-1], Ys[1:])):
        edges[node].append((ny - y, new_node))
        edges[new_node].append((ny - y, node))
    seen = [False] * n
    dist = [float("INF")] * n
    todo = [(0, 0)]
    while todo:
        d, node = heappop(todo)
        if seen[node]:
            continue
        seen[node] = True
        dist[node] = d
        while edges[node]:
            edge = edges[node].pop()
            nd, to = edge
            if dist[to] <= nd:
                continue
            heappush(todo, (nd, to))
    print((sum(dist)))


if __name__ == "__main__":
    main()

import sys

buf = sys.stdin.buffer


class UnionFind:
    def __init__(self, num_of_node):
        self.roots = [-1] * num_of_node
        self.ranks = [1] * num_of_node
        self.groups = num_of_node

    def get_root(self, node):
        root = self.roots[node]
        if root == -1:
            return node
        else:
            root = self.get_root(root)
            self.roots[node] = root
            return root

    def is_same_group(self, node1, node2):
        return self.get_root(node1) == self.get_root(node2)

    def unite(self, node1, node2):
        self.groups -= 1
        root1, root2 = self.get_root(node1), self.get_root(node2)
        rank1, rank2 = self.ranks[root1], self.ranks[root2]
        if rank1 < rank2:
            root1, root2 = root2, root1
        self.roots[root2] = root1
        self.ranks[root2] += self.ranks[root1]


def main():
    n = int(buf.readline())
    XY = list(map(int, buf.read().split()))
    Xs = []
    Ys = []
    for i, (x, y) in enumerate(zip(XY, XY)):
        Xs.append((x - 1, i))
        Ys.append((y - 1, i))
    Xs.sort()
    Ys.sort()
    edges = []
    for i, ((x, node), (nx, new_node)) in enumerate(zip(Xs[:-1], Xs[1:])):
        edges.append((nx - x, node, new_node))
    for i, ((y, node), (ny, new_node)) in enumerate(zip(Ys[:-1], Ys[1:])):
        edges.append((ny - y, node, new_node))
    edges.sort(reverse=True)
    ans = 0
    uf = UnionFind(n)
    while uf.groups != 1:
        d, node1, node2 = edges.pop()
        if uf.is_same_group(node1, node2):
            continue
        uf.unite(node1, node2)
        ans += d
    print(ans)


if __name__ == "__main__":
    main()

-from heapq import heappush, heappop + + +class UnionFind: +    def __init__(self, num_of_node): +        self.roots = [-1] * num_of_node +        self.ranks = [1] * num_of_node +        self.groups = num_of_node + +    def get_root(self, node): +        root = self.roots[node] +        if root == -1: +            return node +        else: +            root = self.get_root(root) +            self.roots[node] = root +            return root + +    def is_same_group(self, node1, node2): +        return self.get_root(node1) == self.get_root(node2) + +    def unite(self, node1, node2): +        self.groups -= 1 +        root1, root2 = self.get_root(node1), self.get_root(node2) +        rank1, rank2 = self.ranks[root1], self.ranks[root2] +        if rank1 < rank2: +            root1, root2 = root2, root1 +        self.roots[root2] = root1 +        self.ranks[root2] += self.ranks[root1] -    edges = [[] for _ in range(n)] +    edges = [] -        edges[node].append((nx - x, new_node)) -        edges[new_node].append((nx - x, node)) +        edges.append((nx - x, node, new_node)) -        edges[node].append((ny - y, new_node)) -        edges[new_node].append((ny - y, node)) -    seen = [False] * n -    dist = [float("INF")] * n -    todo = [(0, 0)] -    while todo: -        d, node = heappop(todo) -        if seen[node]: +        edges.append((ny - y, node, new_node)) +    edges.sort(reverse=True) +    ans = 0 +    uf = UnionFind(n) +    while uf.groups != 1: +        d, node1, node2 = edges.pop() +        if uf.is_same_group(node1, node2): -        seen[node] = True -        dist[node] = d -        while edges[node]: -            edge = edges[node].pop() -            nd, to = edge -            if dist[to] <= nd: -                continue -            heappush(todo, (nd, to)) -    print((sum(dist))) +        uf.unite(node1, node2) +        ans += d +    print(ans)