N = int(eval(input()))

P = [[i, list(map(int, input().split()))] for i in range(N)]



X = sorted([[i, xy[0]] for i, xy in P], key=lambda x: x[1])

Y = sorted([[i, xy[1]] for i, xy in P], key=lambda y: y[1])



Xe = [[X[i][0], X[i+1][0], abs(X[i][1]-X[i+1][1])] for i in range(N-1)]

Ye = [[Y[i][0], Y[i+1][0], abs(Y[i][1]-Y[i+1][1])] for i in range(N-1)]

E = sorted(Xe + Ye, key=lambda e: e[2])





class UnionFind:

    def __init__(self, n):

        self.par = [i for i in range(n+1)]

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

        self.size = [1] * (n+1)



    # 検索

    def find(self, x):

        if self.par[x] == x:

            return x

        else:

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

            return self.par[x]



    # 併合

    def union(self, x, y):

        x = self.find(x)

        y = self.find(y)



        if x == y:

            return



        if 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 same_check(self, x, y):

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





uf = UnionFind(N)

edge_cnt = 0

MST_cost = 0

i = 0



while edge_cnt < N-1:

    a, b, cost = E[i]

    if not uf.same_check(a, b):

        MST_cost += cost

        uf.union(a, b)

        edge_cnt += 1

    i += 1



print(MST_cost)
N = int(eval(input()))

Points = [[i] + list(map(int, input().split())) for i in range(N)]



# x, yそれぞれについてソートして、一番近いところを見れば十分

Edges = []

Points.sort(key=lambda p: p[1])

for i in range(N - 1):

    n1, x1, y1 = Points[i]

    n2, x2, y2 = Points[i + 1]

    Edges.append([n1, n2, x2 - x1])



Points.sort(key=lambda p: p[2])

for i in range(N - 1):

    n1, x1, y1 = Points[i]

    n2, x2, y2 = Points[i + 1]

    Edges.append([n1, n2, y2 - y1])





class UnionFind:

    def __init__(self, n):

        self.par = [i for i in range(n+1)]

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

        self.size = [1] * (n+1)



    # 検索

    def find(self, x):

        if self.par[x] == x:

            return x

        else:

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

            return self.par[x]



    # 併合

    def union(self, x, y):

        x = self.find(x)

        y = self.find(y)



        if x == y:

            return



        if 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 same_check(self, x, y):

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





uf = UnionFind(N)

Edges.sort(key=lambda e: e[2], reverse=True)

MST_cost = 0

i = 0



# 辺のコストが小さいものから、閉路を作らないように、木を構成する

# 最小全域木の必要辺は(頂点数-1)本

while i != N - 1:

    x, y, cost = Edges.pop()

    # 同じ辺集合に属していないならば（閉路が生まれないならば）

    if not uf.same_check(x, y):

        MST_cost += cost

        uf.union(x, y)

        i += 1



print(MST_cost)

N = int(eval(input()))
P = [[i, list(map(int, input().split()))] for i in range(N)]
X = sorted([[i, xy[0]] for i, xy in P], key=lambda x: x[1])
Y = sorted([[i, xy[1]] for i, xy in P], key=lambda y: y[1])
Xe = [[X[i][0], X[i + 1][0], abs(X[i][1] - X[i + 1][1])] for i in range(N - 1)]
Ye = [[Y[i][0], Y[i + 1][0], abs(Y[i][1] - Y[i + 1][1])] for i in range(N - 1)]
E = sorted(Xe + Ye, key=lambda e: e[2])


class UnionFind:
    def __init__(self, n):
        self.par = [i for i in range(n + 1)]
        self.rank = [0] * (n + 1)
        self.size = [1] * (n + 1)

    # 検索
    def find(self, x):
        if self.par[x] == x:
            return x
        else:
            self.par[x] = self.find(self.par[x])
            return self.par[x]

    # 併合
    def union(self, x, y):
        x = self.find(x)
        y = self.find(y)
        if x == y:
            return
        if 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 same_check(self, x, y):
        return self.find(x) == self.find(y)


uf = UnionFind(N)
edge_cnt = 0
MST_cost = 0
i = 0
while edge_cnt < N - 1:
    a, b, cost = E[i]
    if not uf.same_check(a, b):
        MST_cost += cost
        uf.union(a, b)
        edge_cnt += 1
    i += 1
print(MST_cost)

N = int(eval(input()))
Points = [[i] + list(map(int, input().split())) for i in range(N)]
# x, yそれぞれについてソートして、一番近いところを見れば十分
Edges = []
Points.sort(key=lambda p: p[1])
for i in range(N - 1):
    n1, x1, y1 = Points[i]
    n2, x2, y2 = Points[i + 1]
    Edges.append([n1, n2, x2 - x1])
Points.sort(key=lambda p: p[2])
for i in range(N - 1):
    n1, x1, y1 = Points[i]
    n2, x2, y2 = Points[i + 1]
    Edges.append([n1, n2, y2 - y1])


class UnionFind:
    def __init__(self, n):
        self.par = [i for i in range(n + 1)]
        self.rank = [0] * (n + 1)
        self.size = [1] * (n + 1)

    # 検索
    def find(self, x):
        if self.par[x] == x:
            return x
        else:
            self.par[x] = self.find(self.par[x])
            return self.par[x]

    # 併合
    def union(self, x, y):
        x = self.find(x)
        y = self.find(y)
        if x == y:
            return
        if 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 same_check(self, x, y):
        return self.find(x) == self.find(y)


uf = UnionFind(N)
Edges.sort(key=lambda e: e[2], reverse=True)
MST_cost = 0
i = 0
# 辺のコストが小さいものから、閉路を作らないように、木を構成する
# 最小全域木の必要辺は(頂点数-1)本
while i != N - 1:
    x, y, cost = Edges.pop()
    # 同じ辺集合に属していないならば（閉路が生まれないならば）
    if not uf.same_check(x, y):
        MST_cost += cost
        uf.union(x, y)
        i += 1
print(MST_cost)

-P = [[i, list(map(int, input().split()))] for i in range(N)] -X = sorted([[i, xy[0]] for i, xy in P], key=lambda x: x[1]) -Y = sorted([[i, xy[1]] for i, xy in P], key=lambda y: y[1]) -Xe = [[X[i][0], X[i + 1][0], abs(X[i][1] - X[i + 1][1])] for i in range(N - 1)] -Ye = [[Y[i][0], Y[i + 1][0], abs(Y[i][1] - Y[i + 1][1])] for i in range(N - 1)] -E = sorted(Xe + Ye, key=lambda e: e[2]) +Points = [[i] + list(map(int, input().split())) for i in range(N)] +# x, yそれぞれについてソートして、一番近いところを見れば十分 +Edges = [] +Points.sort(key=lambda p: p[1]) +for i in range(N - 1): +    n1, x1, y1 = Points[i] +    n2, x2, y2 = Points[i + 1] +    Edges.append([n1, n2, x2 - x1]) +Points.sort(key=lambda p: p[2]) +for i in range(N - 1): +    n1, x1, y1 = Points[i] +    n2, x2, y2 = Points[i + 1] +    Edges.append([n1, n2, y2 - y1]) -edge_cnt = 0 +Edges.sort(key=lambda e: e[2], reverse=True) -while edge_cnt < N - 1: -    a, b, cost = E[i] -    if not uf.same_check(a, b): +# 辺のコストが小さいものから、閉路を作らないように、木を構成する +# 最小全域木の必要辺は(頂点数-1)本 +while i != N - 1: +    x, y, cost = Edges.pop() +    # 同じ辺集合に属していないならば（閉路が生まれないならば） +    if not uf.same_check(x, y): -        uf.union(a, b) -        edge_cnt += 1 -    i += 1 +        uf.union(x, y) +        i += 1