# Original solution
import heapq
def prim_heap():
    used = [True]*n #True:不使用
    edgelist = []
    for e in edge[0]: #連結なのでedge[0]は必ず存在する
        heapq.heappush(edgelist,e)
    used[0] = False #番号0の頂点を始点とする
    res = 0 #答え
    while len(edgelist) != 0:
        minedge = heapq.heappop(edgelist)
        if not used[minedge[1]]: #取り出した辺の行き先が使用済みなら
            continue #捨てる
        v = minedge[1] #そうでないなら行き先を使用済みにする
        used[v] = False
        for e in edge[v]: #行き先の頂点がつながる辺において
            if used[e[1]]: #その先の頂点が未使用なら
                heapq.heappush(edgelist,e) #次につなげる辺の候補にする
        res += minedge[0] #コストを足す
    return res

#########################
n = int(eval(input()))
L = []
for i in range(n):
    a,b = list(map(int,input().split()))
    L.append([i,a,b])
L = sorted(L, key = lambda x:x[1])
edge = [[] for i in range(n)] # edge[i]:[コスト,行先]
for i in range(n):
    if i == 0:
        edge[L[0][0]].append([min(abs(L[0][1]-L[1][1]),abs(L[0][2]-L[1][2])),L[1][0]])
        edge[L[1][0]].append([min(abs(L[0][1]-L[1][1]),abs(L[0][2]-L[1][2])),L[0][0]])
    elif i == n-1:
        edge[L[n-1][0]].append([min(abs(L[n-1][1]-L[n-2][1]),abs(L[n-1][2]-L[n-2][2])),L[n-2][0]])
        edge[L[n-2][0]].append([min(abs(L[n-1][1]-L[n-2][1]),abs(L[n-1][2]-L[n-2][2])),L[n-1][0]])
    else:
        edge[L[i][0]].append([min(abs(L[i][1]-L[i-1][1]),abs(L[i][2]-L[i-1][2])),L[i-1][0]])
        edge[L[i-1][0]].append([min(abs(L[i][1]-L[i-1][1]),abs(L[i][2]-L[i-1][2])),L[i][0]])
        edge[L[i][0]].append([min(abs(L[i][1]-L[i+1][1]),abs(L[i][2]-L[i+1][2])),L[i+1][0]])
        edge[L[i+1][0]].append([min(abs(L[i][1]-L[i+1][1]),abs(L[i][2]-L[i+1][2])),L[i][0]])
L = sorted(L, key = lambda x:x[2])
for i in range(n):
    if i == 0:
        edge[L[0][0]].append([min(abs(L[0][1]-L[1][1]),abs(L[0][2]-L[1][2])),L[1][0]])
        edge[L[1][0]].append([min(abs(L[0][1]-L[1][1]),abs(L[0][2]-L[1][2])),L[0][0]])
    elif i == n-1:
        edge[L[n-1][0]].append([min(abs(L[n-1][1]-L[n-2][1]),abs(L[n-1][2]-L[n-2][2])),L[n-2][0]])
        edge[L[n-2][0]].append([min(abs(L[n-1][1]-L[n-2][1]),abs(L[n-1][2]-L[n-2][2])),L[n-1][0]])
    else:
        edge[L[i][0]].append([min(abs(L[i][1]-L[i-1][1]),abs(L[i][2]-L[i-1][2])),L[i-1][0]])
        edge[L[i-1][0]].append([min(abs(L[i][1]-L[i-1][1]),abs(L[i][2]-L[i-1][2])),L[i][0]])
        edge[L[i][0]].append([min(abs(L[i][1]-L[i+1][1]),abs(L[i][2]-L[i+1][2])),L[i+1][0]])
        edge[L[i+1][0]].append([min(abs(L[i][1]-L[i+1][1]),abs(L[i][2]-L[i+1][2])),L[i][0]])
print((prim_heap()))

# Optimized solution
n = int(eval(input()))
L = []
ans = 0
for i in range(n):
    a,b = list(map(int,input().split()))
    L.append([a,b,i])
P = []
L.sort()
for i in range(n-1):
    dist = min(abs(L[i][0]-L[i+1][0]),abs(L[i][1]-L[i+1][1]))
    P.append([dist,L[i][2],L[i+1][2]])
L = sorted(L, key = lambda x:x[1])
for i in range(n-1):
    dist = min(abs(L[i][0]-L[i+1][0]),abs(L[i][1]-L[i+1][1]))
    P.append([dist,L[i][2],L[i+1][2]])
P.sort()
par = [i for i in range(n)]
rank = [0]*n
def find(x,par):
    if x == par[x]:
        return par[x]
    else:
        return find(par[x],par)
def unite(x,y,par,rank):
    x = find(x,par)
    y = find(y,par)
    if x != y:
        if rank[x] < rank[y]:
            par[x] = y
        else:
            par[y] = x
            if rank[x] == rank[y]:
                rank[x] += 1
for i in range(len(P)):
    if find(P[i][1],par) != find(P[i][2],par):
        ans += P[i][0]
        unite(P[i][1],P[i][2],par,rank)
print(ans)