# 解説



def solve() -> None:

    from collections import namedtuple

    from heapq import heappush, heappop

    from operator import attrgetter

    pt = namedtuple('pt', 'x y idx')



    n = int(eval(input()))

    cities = []

    for idx in range(n):

        x, y = list(map(int, input().split()))

        cities.append(pt(x=x, y=y, idx=idx))



    g = tuple(set() for _ in range(n))



    xs = sorted(cities, key=attrgetter('x'))

    for a, b in zip(xs, xs[1:]):

        g[a.idx].add((b.x - a.x, b.idx))

        g[b.idx].add((b.x - a.x, a.idx))



    ys = sorted(cities, key=attrgetter('y'))

    for a, b in zip(ys, ys[1:]):

        g[a.idx].add((b.y - a.y, b.idx))

        g[b.idx].add((b.y - a.y, a.idx))



    ret = 0

    h = [(0, 0)]

    used = [False] * n

    count = 0



    while True:

        c, v = heappop(h)

        if used[v]:

            continue

        used[v] = True

        count += 1

        ret += c

        if count == n:

            break

        for c_, u in g[v]:

            if used[u]:

                continue

            heappush(h, (c_, u))



    return ret





if __name__ == '__main__':

    print((solve()))



# 最小全域木

def solve_abc065d():

    from collections import namedtuple

    from operator import attrgetter

    from itertools import tee

    import sys



    input = sys.stdin.readline



    City = namedtuple('City', 'x y idx')

    Edge = namedtuple('Edge', 'cost a b')

    N = int(eval(input()))



    cities = []

    for city_idx in range(N):

        x, y = list(map(int, input().split()))

        c_ = City(x, y, city_idx)

        cities.append(c_)

    cities_x_asc = sorted(cities, key=attrgetter('x'))

    cities_y_asc = sorted(cities, key=attrgetter('y'))



    edges = []



    it_x = iter(cities_x_asc)

    gx1, gx2 = tee(it_x, 2)

    next(gx2)

    for c1, c2 in zip(gx1, gx2):

        d_ = c2.x - c1.x

        e_ = Edge(d_, c1.idx, c2.idx)

        edges.append(e_)

    # x方向にN-1本の辺を張る



    it_y = iter(cities_y_asc)

    gy1, gy2 = tee(it_y, 2)

    next(gy2)

    for c1, c2 in zip(gy1, gy2):

        d_ = c2.y - c1.y

        e_ = Edge(d_, c1.idx, c2.idx)

        edges.append(e_)

    # y方向にN-1本の辺を張る



    edges.sort(key=attrgetter('cost'))



    # <Kruskal’s Algorithm>

    # https://tjkendev.github.io/procon-library/python/graph/min_st_kruskal.html

    # E = [(cost, v, w), ...]

    #   G上の全ての辺(v, w)とそのcostを含むlist



    # Union-Findを使うことで頂点間の連結判定を行う

    *p, = list(range(N))



    def root(x):

        if x == p[x]:

            return x

        p[x] = y = root(p[x])

        return y



    def unite(x, y):

        px = root(x)

        py = root(y)

        if px == py:

            return 0

        if px < py:

            p[py] = px

        else:

            p[px] = py

        return 1



    mi = 0

    for e_ in edges:

        if unite(e_.a, e_.b):

            mi += e_.cost



    # miが最小全域木の解



    print(mi)

    return





if __name__ == '__main__':

    solve_abc065d()

# 解説
def solve() -> None:
    from collections import namedtuple
    from heapq import heappush, heappop
    from operator import attrgetter

    pt = namedtuple("pt", "x y idx")
    n = int(eval(input()))
    cities = []
    for idx in range(n):
        x, y = list(map(int, input().split()))
        cities.append(pt(x=x, y=y, idx=idx))
    g = tuple(set() for _ in range(n))
    xs = sorted(cities, key=attrgetter("x"))
    for a, b in zip(xs, xs[1:]):
        g[a.idx].add((b.x - a.x, b.idx))
        g[b.idx].add((b.x - a.x, a.idx))
    ys = sorted(cities, key=attrgetter("y"))
    for a, b in zip(ys, ys[1:]):
        g[a.idx].add((b.y - a.y, b.idx))
        g[b.idx].add((b.y - a.y, a.idx))
    ret = 0
    h = [(0, 0)]
    used = [False] * n
    count = 0
    while True:
        c, v = heappop(h)
        if used[v]:
            continue
        used[v] = True
        count += 1
        ret += c
        if count == n:
            break
        for c_, u in g[v]:
            if used[u]:
                continue
            heappush(h, (c_, u))
    return ret


if __name__ == "__main__":
    print((solve()))
# 最小全域木

def solve_abc065d():
    from collections import namedtuple
    from operator import attrgetter
    from itertools import tee
    import sys

    input = sys.stdin.readline
    City = namedtuple("City", "x y idx")
    Edge = namedtuple("Edge", "cost a b")
    N = int(eval(input()))
    cities = []
    for city_idx in range(N):
        x, y = list(map(int, input().split()))
        c_ = City(x, y, city_idx)
        cities.append(c_)
    cities_x_asc = sorted(cities, key=attrgetter("x"))
    cities_y_asc = sorted(cities, key=attrgetter("y"))
    edges = []
    it_x = iter(cities_x_asc)
    gx1, gx2 = tee(it_x, 2)
    next(gx2)
    for c1, c2 in zip(gx1, gx2):
        d_ = c2.x - c1.x
        e_ = Edge(d_, c1.idx, c2.idx)
        edges.append(e_)
    # x方向にN-1本の辺を張る
    it_y = iter(cities_y_asc)
    gy1, gy2 = tee(it_y, 2)
    next(gy2)
    for c1, c2 in zip(gy1, gy2):
        d_ = c2.y - c1.y
        e_ = Edge(d_, c1.idx, c2.idx)
        edges.append(e_)
    # y方向にN-1本の辺を張る
    edges.sort(key=attrgetter("cost"))
    # <Kruskal’s Algorithm>
    # https://tjkendev.github.io/procon-library/python/graph/min_st_kruskal.html
    # E = [(cost, v, w), ...]
    #   G上の全ての辺(v, w)とそのcostを含むlist
    # Union-Findを使うことで頂点間の連結判定を行う
    (*p,) = list(range(N))

    def root(x):
        if x == p[x]:
            return x
        p[x] = y = root(p[x])
        return y

    def unite(x, y):
        px = root(x)
        py = root(y)
        if px == py:
            return 0
        if px < py:
            p[py] = px
        else:
            p[px] = py
        return 1

    mi = 0
    for e_ in edges:
        if unite(e_.a, e_.b):
            mi += e_.cost
    # miが最小全域木の解
    print(mi)
    return


if __name__ == "__main__":
    solve_abc065d()

-# 解説 -def solve() -> None: +def solve_abc065d(): -    from heapq import heappush, heappop +    from itertools import tee +    import sys -    pt = namedtuple("pt", "x y idx") -    n = int(eval(input())) +    input = sys.stdin.readline +    City = namedtuple("City", "x y idx") +    Edge = namedtuple("Edge", "cost a b") +    N = int(eval(input())) -    for idx in range(n): +    for city_idx in range(N): -        cities.append(pt(x=x, y=y, idx=idx)) -    g = tuple(set() for _ in range(n)) -    xs = sorted(cities, key=attrgetter("x")) -    for a, b in zip(xs, xs[1:]): -        g[a.idx].add((b.x - a.x, b.idx)) -        g[b.idx].add((b.x - a.x, a.idx)) -    ys = sorted(cities, key=attrgetter("y")) -    for a, b in zip(ys, ys[1:]): -        g[a.idx].add((b.y - a.y, b.idx)) -        g[b.idx].add((b.y - a.y, a.idx)) -    ret = 0 -    h = [(0, 0)] -    used = [False] * n -    count = 0 -    while True: -        c, v = heappop(h) -        if used[v]: -            continue -        used[v] = True -        count += 1 -        ret += c -        if count == n: -            break -        for c_, u in g[v]: -            if used[u]: -                continue -            heappush(h, (c_, u)) -    return ret +        c_ = City(x, y, city_idx) +        cities.append(c_) +    cities_x_asc = sorted(cities, key=attrgetter("x")) +    cities_y_asc = sorted(cities, key=attrgetter("y")) +    edges = [] +    it_x = iter(cities_x_asc) +    gx1, gx2 = tee(it_x, 2) +    next(gx2) +    for c1, c2 in zip(gx1, gx2): +        d_ = c2.x - c1.x +        e_ = Edge(d_, c1.idx, c2.idx) +        edges.append(e_) +    # x方向にN-1本の辺を張る +    it_y = iter(cities_y_asc) +    gy1, gy2 = tee(it_y, 2) +    next(gy2) +    for c1, c2 in zip(gy1, gy2): +        d_ = c2.y - c1.y +        e_ = Edge(d_, c1.idx, c2.idx) +        edges.append(e_) +    # y方向にN-1本の辺を張る +    edges.sort(key=attrgetter("cost")) +    # <Kruskal’s Algorithm> +    # https://tjkendev.github.io/procon-library/python/graph/min_st_kruskal.html +    # E = [(cost, v, w), ...] +    #   G上の全ての辺(v, w)とそのcostを含むlist +    # Union-Findを使うことで頂点間の連結判定を行う +    (*p,) = list(range(N)) + +    def root(x): +        if x == p[x]: +            return x +        p[x] = y = root(p[x]) +        return y + +    def unite(x, y): +        px = root(x) +        py = root(y) +        if px == py: +            return 0 +        if px < py: +            p[py] = px +        else: +            p[px] = py +        return 1 + +    mi = 0 +    for e_ in edges: +        if unite(e_.a, e_.b): +            mi += e_.cost +    # miが最小全域木の解 +    print(mi) +    return -    print((solve())) -# 最小全域木 +    solve_abc065d()