import heapq

N = int(eval(input()))

town = []

for i in range(N):

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

    town.append((x, y, i))



uf = [i for i in range(N)]      #uf[i]==iであれば根



def root(x):

    if x == uf[x]:

        return x

    else:

        r = root(uf[x])

        uf[x] = r

        return r



def isSame(x,y):

    return root(x) == root(y)



def unite(x, y):

    x = root(x)

    y = root(y)

    if x==y:

        return

    uf[x] = y

    return



road = []

town.sort() #x座標でソート O(NlogN + N)

for i in range(N-1):

    x1, _, ind1 = town[i]

    x2, _, ind2 = town[i+1]

    cost = abs(x2 - x1)

    heapq.heappush(road, (cost, ind1, ind2))

town.sort(key = lambda x:x[1]) #y座標でソート O(NlogN + N)

for i in range(N-1):

    _, x1, ind1 = town[i]

    _, x2, ind2 = town[i+1]

    cost = abs(x2 - x1)

    heapq.heappush(road, (cost, ind1, ind2))



ans = 0

while road: #O(2N)

    cost, i, j = heapq.heappop(road)

    if isSame(i,j):

        continue

    unite(i, j)

    ans += cost



print(ans)

from operator import itemgetter

import sys

input = sys.stdin.buffer.readline

sys.setrecursionlimit(10 ** 7)





class UF_tree:

    def __init__(self, n):

        self.root = [-1] * (n + 1)  # -1ならそのノードが根,で絶対値が木の要素数

        self.rank = [0] * (n + 1)



    def find(self, x):  # xの根となる要素番号を返す

        if self.root[x] < 0:

            return x

        else:

            self.root[x] = self.find(self.root[x])

            return self.root[x]



    def isSame(self, x, y):

        return self.find(x) == self.find(y)



    def unite(self, x, y):

        x = self.find(x)

        y = self.find(y)

        if x == y:

            return

        elif self.rank[x] < self.rank[y]:

            self.root[y] += self.root[x]

            self.root[x] = y

        else:

            self.root[x] += self.root[y]

            self.root[y] = x

            if self.rank[x] == self.rank[y]:

                self.rank[x] += 1



    def getNodeLen(self, x):

        return -self.root[self.find(x)]





if __name__ == "__main__":

    N = int(eval(input()))

    XY = []

    for i in range(N):

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

        XY.append((x, y, i))



    edge = []

    XY.sort()

    for (x1, _, i), (x2, _, j) in zip(XY[:-1], XY[1:]):

        edge.append((x2 - x1, i, j))



    XY.sort(key=itemgetter(1))

    for (_, x1, i), (_, x2, j) in zip(XY[:-1], XY[1:]):

        edge.append((x2 - x1, i, j))



    uf = UF_tree(N + 10)

    edge.sort()

    ans = 0

    for cost, x, y in edge:

        if uf.isSame(x, y):

            continue

        uf.unite(x, y)

        ans += cost

    print(ans)
import heapq

N = int(eval(input()))
town = []
for i in range(N):
    x, y = list(map(int, input().split()))
    town.append((x, y, i))
uf = [i for i in range(N)]  # uf[i]==iであれば根


def root(x):
    if x == uf[x]:
        return x
    else:
        r = root(uf[x])
        uf[x] = r
        return r


def isSame(x, y):
    return root(x) == root(y)


def unite(x, y):
    x = root(x)
    y = root(y)
    if x == y:
        return
    uf[x] = y
    return


road = []
town.sort()  # x座標でソート O(NlogN + N)
for i in range(N - 1):
    x1, _, ind1 = town[i]
    x2, _, ind2 = town[i + 1]
    cost = abs(x2 - x1)
    heapq.heappush(road, (cost, ind1, ind2))
town.sort(key=lambda x: x[1])  # y座標でソート O(NlogN + N)
for i in range(N - 1):
    _, x1, ind1 = town[i]
    _, x2, ind2 = town[i + 1]
    cost = abs(x2 - x1)
    heapq.heappush(road, (cost, ind1, ind2))
ans = 0
while road:  # O(2N)
    cost, i, j = heapq.heappop(road)
    if isSame(i, j):
        continue
    unite(i, j)
    ans += cost
print(ans)

from operator import itemgetter
import sys

input = sys.stdin.buffer.readline
sys.setrecursionlimit(10**7)


class UF_tree:
    def __init__(self, n):
        self.root = [-1] * (n + 1)  # -1ならそのノードが根,で絶対値が木の要素数
        self.rank = [0] * (n + 1)

    def find(self, x):  # xの根となる要素番号を返す
        if self.root[x] < 0:
            return x
        else:
            self.root[x] = self.find(self.root[x])
            return self.root[x]

    def isSame(self, x, y):
        return self.find(x) == self.find(y)

    def unite(self, x, y):
        x = self.find(x)
        y = self.find(y)
        if x == y:
            return
        elif self.rank[x] < self.rank[y]:
            self.root[y] += self.root[x]
            self.root[x] = y
        else:
            self.root[x] += self.root[y]
            self.root[y] = x
            if self.rank[x] == self.rank[y]:
                self.rank[x] += 1

    def getNodeLen(self, x):
        return -self.root[self.find(x)]


if __name__ == "__main__":
    N = int(eval(input()))
    XY = []
    for i in range(N):
        x, y = list(map(int, input().split()))
        XY.append((x, y, i))
    edge = []
    XY.sort()
    for (x1, _, i), (x2, _, j) in zip(XY[:-1], XY[1:]):
        edge.append((x2 - x1, i, j))
    XY.sort(key=itemgetter(1))
    for (_, x1, i), (_, x2, j) in zip(XY[:-1], XY[1:]):
        edge.append((x2 - x1, i, j))
    uf = UF_tree(N + 10)
    edge.sort()
    ans = 0
    for cost, x, y in edge:
        if uf.isSame(x, y):
            continue
        uf.unite(x, y)
        ans += cost
    print(ans)

-import heapq +from operator import itemgetter +import sys -N = int(eval(input())) -town = [] -for i in range(N): -    x, y = list(map(int, input().split())) -    town.append((x, y, i)) -uf = [i for i in range(N)]  # uf[i]==iであれば根 +input = sys.stdin.buffer.readline +sys.setrecursionlimit(10**7) -def root(x): -    if x == uf[x]: -        return x -    else: -        r = root(uf[x]) -        uf[x] = r -        return r +class UF_tree: +    def __init__(self, n): +        self.root = [-1] * (n + 1)  # -1ならそのノードが根,で絶対値が木の要素数 +        self.rank = [0] * (n + 1) + +    def find(self, x):  # xの根となる要素番号を返す +        if self.root[x] < 0: +            return x +        else: +            self.root[x] = self.find(self.root[x]) +            return self.root[x] + +    def isSame(self, x, y): +        return self.find(x) == self.find(y) + +    def unite(self, x, y): +        x = self.find(x) +        y = self.find(y) +        if x == y: +            return +        elif self.rank[x] < self.rank[y]: +            self.root[y] += self.root[x] +            self.root[x] = y +        else: +            self.root[x] += self.root[y] +            self.root[y] = x +            if self.rank[x] == self.rank[y]: +                self.rank[x] += 1 + +    def getNodeLen(self, x): +        return -self.root[self.find(x)] -def isSame(x, y): -    return root(x) == root(y) - - -def unite(x, y): -    x = root(x) -    y = root(y) -    if x == y: -        return -    uf[x] = y -    return - - -road = [] -town.sort()  # x座標でソート O(NlogN + N) -for i in range(N - 1): -    x1, _, ind1 = town[i] -    x2, _, ind2 = town[i + 1] -    cost = abs(x2 - x1) -    heapq.heappush(road, (cost, ind1, ind2)) -town.sort(key=lambda x: x[1])  # y座標でソート O(NlogN + N) -for i in range(N - 1): -    _, x1, ind1 = town[i] -    _, x2, ind2 = town[i + 1] -    cost = abs(x2 - x1) -    heapq.heappush(road, (cost, ind1, ind2)) -ans = 0 -while road:  # O(2N) -    cost, i, j = heapq.heappop(road) -    if isSame(i, j): -        continue -    unite(i, j) -    ans += cost -print(ans) +if __name__ == "__main__": +    N = int(eval(input())) +    XY = [] +    for i in range(N): +        x, y = list(map(int, input().split())) +        XY.append((x, y, i)) +    edge = [] +    XY.sort() +    for (x1, _, i), (x2, _, j) in zip(XY[:-1], XY[1:]): +        edge.append((x2 - x1, i, j)) +    XY.sort(key=itemgetter(1)) +    for (_, x1, i), (_, x2, j) in zip(XY[:-1], XY[1:]): +        edge.append((x2 - x1, i, j)) +    uf = UF_tree(N + 10) +    edge.sort() +    ans = 0 +    for cost, x, y in edge: +        if uf.isSame(x, y): +            continue +        uf.unite(x, y) +        ans += cost +    print(ans)