CodeEff/ECCO huggingface dataset:
# Original solution
from heapq import heappush, heappop


class UnionFind():
    def __init__(self, n):
        self.parents = list(range(n))

    def find(self, x):
        if self.parents[x] == x:
            return x
        else:
            self.parents[x] = self.find(self.parents[x])
            return self.parents[x]

    def union(self, x, y):
        x = self.find(x)
        y = self.find(y)
        if x != y:
            self.parents[y] = x

N = int(eval(input()))
q = []
ans = 0
S = UnionFind(N)
x = []
y = []

for i in range(N):
    p,r = list(map(int, input().split()))
    x.append([p,i])
    y.append([r,i])

x.sort()
y.sort()
for i in range(N-1):
    x1, i1 = x[i]
    y1, j1 = y[i]
    x2, i2 = x[i+1]
    y2, j2 = y[i+1]
    heappush(q, (abs(x1-x2), i1, i2))
    heappush(q, (abs(y1-y2), j1, j2))

heappush(q, (abs(x[N-1][0]-x[0][0]), x[N-1][1], x[0][1]))
heappush(q, (abs(y[N-1][0]-y[0][0]), y[N-1][1], y[0][1]))
# クラスカル法
while len(q) > 0:
    d, a, b = heappop(q)
    if S.find(a) != S.find(b):
        ans += d
        S.union(a, b)
print(ans)

# Optimized solution
from heapq import heappop, heappush

class UnionFind():
    def __init__(self, n):
        self.parents = list(range(n))
        self.size = [1] * n

    def find(self, x):
        if self.parents[x] == x:
            return x
        else:
            self.parents[x] = self.find(self.parents[x])
            return self.parents[x]

    def union(self, x, y):
        x = self.find(x)
        y = self.find(y)
        if x != y:
            if self.size[x] < self.size[y]:
                x,y = y,x
            self.parents[y] = x
            self.size[x] += self.size[y]

N = int(eval(input()))
x = [None] * N
y = [None] * N
for i in range(N):
    a, b = list(map(int, input().split()))
    x[i] = (a,i)
    y[i] = (b,i)

x.sort()
y.sort()
q = []
for i in range(N-1):
    heappush(q, (abs(x[i][0]-x[i+1][0]), x[i][1], x[i+1][1]))
    heappush(q, (abs(y[i][0]-y[i+1][0]), y[i][1], y[i+1][1]))

uf = UnionFind(N)
ans = 0
# クラスカル法
while len(q) > 0:
    w, s, t = heappop(q)
    if uf.find(s) != uf.find(t):
        ans += w
        uf.union(s,t)
print(ans)
# Original solution
import heapq

N = int(eval(input()))
place = []
d = {}
j = 0
for i in range(N):
    x, y = list(map(int, input().split()))
    place.append((x,y))
    if not (x,y) in d:
        d[(x,y)] = j
        j += 1
N = j

sort_x = sorted(place)
sort_y = sorted(place, key = lambda k:k[1])

edge=[[] for i in range(N)]
flag = False
for x,y in sort_x:
    now = d[(x,y)]
    if flag:
        edge[before].append([x-before_x,now])
        edge[now].append([x-before_x,d[(before_x,before_y)]])
    else:
        flag = True
    before_x = x
    before_y = y
    before = now

flag = False
for x,y in sort_y:
    now = d[(x,y)]
    if flag:
        edge[before].append([y-before_y,now])
        edge[now].append([y-before_y,before])
    else:
        flag = True
    before_x = x
    before_y = y
    before = now

used = [True]*N
edgelist = []
for e in edge[0]:
    heapq.heappush(edgelist,e)
used[0] = False
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]

print(res)

# Optimized solution
class UnionFind():
    def __init__(self, n):
        self.n = n
        self.parents = [-1]*n
    
    def find(self, x):
        if self.parents[x] < 0:
            return x
        else:
            self.parents[x] = self.find(self.parents[x])
            return self.parents[x]
    def union(self, x, y):
        x = self.find(x)
        y = self.find(y)

        if x == y:
            return

        if self.parents[x] > self.parents[y]:
            x, y = y, x

        self.parents[x] += self.parents[y]
        self.parents[y] = x
    
    def size(self, x):
        return -self.parents[self.find(x)]

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

    def members(self, x):
        root = self.find(x)
        return [i for i in range(self.n) if self.find(i) == root]

    def roots(self):
        return [i for i, x in enumerate(self.parents) if x < 0]

    def group_count(self):
        return len(self.roots())

    def all_group_members(self):
        return {r: self.members(r) for r in self.roots()}

    def __str__(self):
        return '\n'.join('{}: {}'.format(r, self.members(r)) for r in self.roots())


N = int(eval(input()))
xy = []
uf = UnionFind(N)
d = {}
j = 0
for i in range(N):
    x, y = list(map(int, input().split()))
    if not (x,y) in d:
        d[(x,y)] = j
        xy.append((x,y))
        j += 1
N = len(xy)

xy = sorted(xy, key = lambda x:x[0])

root = []
for i in range(N-1):
    before_x, before_y = xy[i]
    x, y = xy[i+1]
    root.append((d[xy[i]],d[xy[i+1]],x - before_x))

xy = sorted(xy, key = lambda x:x[1])

for i in range(N-1):
    before_x, before_y = xy[i]
    x, y = xy[i+1]
    root.append((d[xy[i]],d[xy[i+1]],y - before_y))

root = sorted(root, key = lambda x:x[2])

ans = 0
for s,g,c in root:
    if uf.same(s,g):
        continue
    else:
        uf.union(s,g)
        ans += c

print(ans)
# Original solution
#16:15
n = int(eval(input()))
xyi = []
for i in range(n):
  xyi.append(list(map(int,input().split())) + [i])
xyi.sort()
road = []
for j in range(n-1):
  road.append([xyi[j+1][0]-xyi[j][0],xyi[j][2],xyi[j+1][2]])
xyi.sort(key = lambda x: x[1])
for j in range(n-1):
  road.append([xyi[j+1][1]-xyi[j][1],xyi[j][2],xyi[j+1][2]])
road.sort()
pre = [i for i in range(n)]
ans = 0
for k in range(2*n-2):
  d,I,J = road[k]
  ii = []
  ic = 0
  jj = []
  jc = 0
  while pre[I] != I:
    ii.append(I)
    ic += 1
    I = pre[I]
  while pre[J] != J:
    jj.append(J)
    jc += 1
    J = pre[J]
  if I != J:
    ans += d
    if ic >= jc:
      for Js in jj:
        pre[Js] = I
      pre[J] = I
    else:
      for Is in ii:
        pre[Is] = J
      pre[I] = J
print(ans)

# Optimized solution
#16:15
n = int(eval(input()))
xyi = []
for i in range(n):
  xyi.append(list(map(int,input().split())) + [i])
xyi.sort()
road = []
for j in range(n-1):
  road.append([xyi[j+1][0]-xyi[j][0],xyi[j][2],xyi[j+1][2]])
xyi.sort(key = lambda x: x[1])
for j in range(n-1):
  road.append([xyi[j+1][1]-xyi[j][1],xyi[j][2],xyi[j+1][2]])
road.sort()
pre = [i for i in range(n)]
ans = 0
for k in range(2*n-2):
  d,I,J = road[k]
  ii = []
  jj = []
  while pre[I] != I:
    ii.append(I)
    I = pre[I]
  for Is in ii:
    pre[Is] = I
  while pre[J] != J:
    jj.append(J)
    J = pre[J]
  for Js in jj:
    pre[Js] = J
  if I != J:
    pre[J] = I
    ans += d
print(ans)
# Original solution
import heapq
n=int(eval(input()))
x=[]
y=[]
for i in range(n):
  xx,yy=list(map(int,input().split()))
  x.append([xx,i])
  y.append([yy,i])
x.sort()
y.sort()
px=[]
py=[]
for i in range(n-1):
  px.append([x[i+1][0]-x[i][0],x[i][1],x[i+1][1]])
  py.append([y[i+1][0]-y[i][0],y[i][1],y[i+1][1]])
p=px+py
x=[]
y=[]
px=[]
py=[]
heapq.heapify(p)
r=[i for i in range(n)]
rank=[1 for i in range(n)]
def root(x):
  if x==r[x]:
    return x
  else:
    r[x]=root(r[x])
    return r[x]
def union(x,y):
  rx=root(x)
  ry=root(y)
  if rank[rx]>rank[ry]:
    r[rx]=ry
    rank[rx]+=rank[ry]
  else:
    r[ry]=rx
    rank[ry]+=rank[rx]
ans=0
while p:
  path=heapq.heappop(p)
  if root(path[1])==root(path[2]):
    continue
  union(path[1],path[2])
  ans+=path[0]
print(ans)

# Optimized solution
n=int(eval(input()))
x=[]
y=[]
for i in range(n):
  xx,yy=list(map(int,input().split()))
  x.append([xx,i])
  y.append([yy,i])
x.sort()
y.sort()
px=[]
py=[]
for i in range(n-1):
  px.append([x[i+1][0]-x[i][0],x[i][1],x[i+1][1]])
  py.append([y[i+1][0]-y[i][0],y[i][1],y[i+1][1]])
p=px+py
x=[]
y=[]
px=[]
py=[]
p.sort()
r=[i for i in range(n)]
rank=[1 for i in range(n)]
def root(x):
  if x==r[x]:
    return x
  else:
    r[x]=root(r[x])
    return r[x]
def union(path):
  rx=root(path[1])
  ry=root(path[2])
  if rx==ry:
    return 0
  else:
    if rank[rx]>rank[ry]:
      r[rx]=ry
      rank[rx]+=rank[ry]
    else:
      r[ry]=rx
      rank[ry]+=rank[rx]
    return path[0]
ans=0
for i in range(len(p)):
  ans+=union(p[i])
print(ans)
# Original solution
n=int(eval(input()))
x=[]
y=[]
for i in range(n):
  xx,yy=list(map(int,input().split()))
  x.append([xx,i])
  y.append([yy,i])
x.sort()
y.sort()
px=[]
py=[]
for i in range(n-1):
  px.append([x[i+1][0]-x[i][0],x[i][1],x[i+1][1]])
  py.append([y[i+1][0]-y[i][0],y[i][1],y[i+1][1]])
p=px+py
x=[]
y=[]
px=[]
py=[]
p.sort()
r=[i for i in range(n)]
rank=[1 for i in range(n)]
def root(x):
  if x==r[x]:
    return x
  else:
    r[x]=root(r[x])
    return r[x]
def union(path):
  rx=root(path[1])
  ry=root(path[2])
  if rx==ry:
    return 0
  else:
    if rank[rx]>rank[ry]:
      r[rx]=ry
      rank[rx]+=rank[ry]
    else:
      r[ry]=rx
      rank[ry]+=rank[rx]
    return path[0]
ans=0
for i in range(len(p)):
  ans+=union(p[i])
print(ans)

# Optimized solution
n=int(eval(input()))
x=[]
y=[]
for i in range(n):
  xx,yy=list(map(int,input().split()))
  x.append([xx,i])
  y.append([yy,i])
x.sort()
y.sort()
px=[[x1-x0,i0,i1] for (x0,i0),(x1,i1) in zip(x,x[1:])]
py=[[y1-y0,i0,i1] for (y0,i0),(y1,i1) in zip(y,y[1:])]
p=px+py
x=[]
y=[]
px=[]
py=[]
p.sort()
r=[i for i in range(n)]
rank=[1 for i in range(n)]
def root(x):
  if x==r[x]:
    return x
  else:
    r[x]=root(r[x])
    return r[x]
def union(path):
  rx=root(path[1])
  ry=root(path[2])
  if rx==ry:
    return 0
  else:
    if rank[rx]>rank[ry]:
      r[rx]=ry
      rank[rx]+=rank[ry]
    else:
      r[ry]=rx
      rank[ry]+=rank[rx]
    return path[0]
ans=0
for i in range(len(p)):
  ans+=union(p[i])
print(ans)
# Original solution
import operator
import sys

# sys.stdin = open('d1.in')


def read_int_list():
    return list(map(int, input().split()))


def read_str_list():
    return input().split()


def read_int():
    return int(eval(input()))


def read_str():
    return eval(input())


p = []
rank = []


def make_set(x):
    p[x] = x
    rank[x] = 0


def _union(x, y):
    link(find_set(x), find_set(y))


def link(x, y):
    if rank[x] > rank[y]:
        p[y] = x
    else:
        p[x] = y
        if rank[x] == rank[y]:
            rank[x] += 1


def find_set(x):
    if x != p[x]:
        p[x] = find_set(p[x])
    return p[x]


def solve():
    n = read_int()
    a = [read_int_list() for i in range(n)]
    global p, rank
    p = [0] * n
    rank = [0] * n

    for x in range(n):
        make_set(x)

    def get_cost(i, j):
        return min(abs(a[i][0] - a[j][0]), abs(a[i][1] - a[j][1]))

    roads = []
    for j in range(2):
        l = sorted(list(range(n)), key=lambda i: a[i][j])
        for i in range(n - 1):
            cost = get_cost(l[i], l[i + 1])
            road = (cost, l[i], l[i + 1])
            roads.append(road)
    roads.sort()

    res = 0
    for road in roads:
        c, u, v = road
        if find_set(u) != find_set(v):
            res += c
            _union(u, v)
    return res


def main():
    res = solve()
    print(res)


main()


# Optimized solution
import sys

# sys.stdin = open('d1.in')


def read_int_list():
    return list(map(int, input().split()))


def read_str_list():
    return input().split()


def read_int():
    return int(eval(input()))


def read_str():
    return eval(input())


p = []
rank = []


def make_set(x):
    p[x] = x
    rank[x] = 0


def _union(x, y):
    link(find_set(x), find_set(y))


def link(x, y):
    if rank[x] > rank[y]:
        p[y] = x
    else:
        p[x] = y
        if rank[x] == rank[y]:
            rank[x] += 1


def find_set(x):
    if x != p[x]:
        p[x] = find_set(p[x])
    return p[x]


def solve():
    n = read_int()
    a = [read_int_list() for i in range(n)]
    global p, rank
    p = [0] * n
    rank = [0] * n

    for x in range(n):
        make_set(x)

    def get_cost(i, j):
        return min(abs(a[i][0] - a[j][0]), abs(a[i][1] - a[j][1]))

    roads = []
    for j in range(2):
        l = sorted(list(range(n)), key=lambda i: a[i][j])
        for i in range(n - 1):
            cost = get_cost(l[i], l[i + 1])
            road = (cost, l[i], l[i + 1])
            roads.append(road)
    roads.sort()

    res = 0
    m = 0
    for road in roads:
        c, u, v = road
        if find_set(u) != find_set(v):
            res += c
            m += 1
            _union(u, v)
        if m == n - 1:
            break
    return res


def main():
    res = solve()
    print(res)


main()
# Original solution
N = int(eval(input()))
z = [tuple(map(int,input().split())) for i in range(N)]
z.sort()
y = [(z[i][1],i) for i in range(N)]
y.sort()
cost = [[] for i in range(N)]
for i in range(N-1):
    j = y[i][1]
    cost[i].append((i-1,min(abs(z[i][0]-z[i-1][0]),abs(z[i][1]-z[i-1][1]))))
    j_ = y[i-1][1]
    cost[j].append((j_,min(abs(y[i][0]-y[i-1][0]),abs(z[j][0]-z[j_][0]))))
    cost[i].append((i+1,min(abs(z[i+1][0]-z[i][0]),abs(z[i+1][1]-z[i][1]))))
    j_ = y[i+1][1]
    cost[j].append((j_,min(abs(y[i+1][0]-y[i][0]),abs(z[j_][1]-z[j][1]))))

i = N-1
j = y[i][1]
cost[i].append((i-1,min(abs(z[i][0]-z[i-1][0]),abs(z[i][1]-z[i-1][1]))))
j_ = y[i-1][1]
cost[j].append((j_,min(abs(y[i][0]-y[i-1][0]),abs(z[j][0]-z[j_][0]))))


import heapq

def prim(cost):
    V = len(cost)
    res = 0
    mincost = [float('inf')]*V
    used = [False]*V
    hq = []
    mincost[0] = 0
    heapq.heappush(hq,(0,0))
    done = 0
    while hq:
        weight,u = heapq.heappop(hq)
        if not used[u]:
            used[u] = True
            done += 1
            res += weight
            mincost[u] = weight
            for v, v_cost in cost[u]:
                if not used[v]:
                    heapq.heappush(hq,(v_cost,v))
            if done == V:
                break
    return res

print((prim(cost)))

# Optimized solution
N = int(eval(input()))
z = [tuple(map(int,input().split())) for i in range(N)]
z.sort()
y = [(z[i][1],i) for i in range(N)]
y.sort()
cost = [[] for i in range(N)]
for i in range(N-1):
    j = y[i][1]
    cost[i].append((i-1,min(abs(z[i][0]-z[i-1][0]),abs(z[i][1]-z[i-1][1]))))
    j_ = y[i-1][1]
    cost[j].append((j_,min(abs(y[i][0]-y[i-1][0]),abs(z[j][0]-z[j_][0]))))
    cost[i].append((i+1,min(abs(z[i+1][0]-z[i][0]),abs(z[i+1][1]-z[i][1]))))
    j_ = y[i+1][1]
    cost[j].append((j_,min(abs(y[i+1][0]-y[i][0]),abs(z[j_][1]-z[j][1]))))

i = N-1
j = y[i][1]
cost[i].append((i-1,min(abs(z[i][0]-z[i-1][0]),abs(z[i][1]-z[i-1][1]))))
j_ = y[i-1][1]
cost[j].append((j_,min(abs(y[i][0]-y[i-1][0]),abs(z[j][0]-z[j_][0]))))


import heapq

def prim(cost):
    V = len(cost)
    res = 0
    mincost = [float('inf')]*V
    used = [False]*V
    hq = []
    mincost[0] = 0
    heapq.heappush(hq,(0,0))
    while hq:
        weight,u = heapq.heappop(hq)
        if not used[u]:
            used[u] = True
            res += weight
            mincost[u] = weight
            for v, v_cost in cost[u]:
                if not used[v]:
                    heapq.heappush(hq,(v_cost,v))
    return res

print((prim(cost)))
# Original solution
N=int(eval(input()))
city=[]
for i in range(N):
    x,y=list(map(int,input().split()))
    city.append((i,x,y))
city.sort(key=lambda x:x[1])
data=[]
for i in range(N-1):
    data.append((city[i][0],city[i+1][0],city[i+1][1]-city[i][1]))
city.sort(key=lambda y:y[2])
for i in range(N-1):
    data.append((city[i][0],city[i+1][0],city[i+1][2]-city[i][2]))
data.sort(key=lambda d:d[2])
idx=[-1]*N
def find(idx,x):
    if idx[x]<0:
        return x
    elif idx[x]>=0:
        idx[x]=find(idx,idx[x])
        return idx[x]
ans=0
for q in range(len(data)):
    i,j,d=data[q]
    iidx=find(idx,i)
    jidx=find(idx,j)
    if iidx==jidx:
        continue
    elif idx[iidx]<=idx[jidx]:
        idx[iidx]+=idx[jidx]
        idx[jidx]=iidx
        ans+=d
    elif idx[iidx]>idx[jidx]:
        idx[jidx]+=idx[iidx]
        idx[iidx]=jidx
        ans+=d
print(ans)


# Optimized solution
N=int(eval(input()))
city=[0]*N
for i in range(N):
    x,y=list(map(int,input().split()))
    city[i]=(i,x,y)
city.sort(key=lambda x:x[1])
data=[(city[i][0],city[i+1][0],city[i+1][1]-city[i][1]) for i in range(N-1)]
city.sort(key=lambda x:x[2])
data+=[(city[i][0],city[i+1][0],city[i+1][2]-city[i][2]) for i in range(N-1)]
data.sort(key=lambda x:x[2])
root=[-1]*N
def search(i):
    global root
    if root[i]>=0:
        root[i]=search(root[i])
        return root[i]
    return i
cost=0
for i,j,k in data:
    ri=search(i)
    rj=search(j)
    if ri==rj:
        continue
    elif root[ri]<=root[rj]:
        cost+=k
        root[ri]+=root[rj]
        root[rj]=ri
    elif root[ri]>root[rj]:
        cost+=k
        root[rj]+=root[ri]
        root[ri]=rj
print(cost)
# Original solution
import sys
sys.setrecursionlimit(10**9)
input = sys.stdin.readline

import heapq
n = int(eval(input()))
l = [[0, 0] for i in range(n)]
for i in range(n):
  x, y = list(map(int, input().split()))
  l[i][0] = x
  l[i][1] = y
  
graph = []
for i in range(n-1):
  x1, y1 = l[i]
  for j in range(i, n):
    x2, y2 = l[j]
    graph.append((min(abs(x1-x2), abs(y1-y2)), i, j))
    graph.append((min(abs(x1-x2), abs(y1-y2)), j, i))

#union find
def Find(x, par):
  if par[x] < 0:
    return x
  else:
    # 経路圧縮
    par[x] = Find(par[x], par)
    return par[x]

def Unite(x, y, par, rank):
  x = Find(x, par)
  y = Find(y, par)
  
  if x != y:
    # rankの低い方を高い方につなげる
    if rank[x] < rank[y]:
      par[y] += par[x]
      par[x] = y
    else:
      par[x] += par[y]
      par[y] = x
      if rank[x] == rank[y]:
        rank[x] += 1
    
def Same(x, y, par):
  return Find(x, par) == Find(y, par)
 
def Size(x, par):
  return -par[Find(x)]

#print(graph)
graph.sort()
par = [-1]*n
rank = [0]*n

cost = 0

for d, p, q in graph:
  if not Same(p, q, par):
    cost += d
    Unite(p, q, par, rank)

print(cost)

# Optimized solution
import sys
input = sys.stdin.buffer.readline

n = int(eval(input()))
P = []
for i in range(n):
    x, y = list(map(int, input().split()))
    P.append((x, y, i))

import heapq
def prim_heap():
    used = [True]*n
    edgelist = []
    for e in edge[0]:
        heapq.heappush(edgelist, e)
        used[0] = False
    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

P.sort()
edge = [[] for _ in range(n)]
for i in range(n-1):
    d = min(abs(P[i+1][0]-P[i][0]), abs(P[i+1][1]-P[i][1]))
    edge[P[i][2]].append((d, P[i+1][2]))
    edge[P[i+1][2]].append((d, P[i][2]))

P.sort(key = lambda x: x[1])
for i in range(n-1):
    d = min(abs(P[i+1][0]-P[i][0]), abs(P[i+1][1]-P[i][1]))
    edge[P[i][2]].append((d, P[i+1][2]))
    edge[P[i+1][2]].append((d, P[i][2]))

print((prim_heap()))
# Original solution
import bisect
import sys
import heapq
N = int(eval(input()))
city_ls = list()
for i in range(N):
    city_ls.append([int(i) for i in sys.stdin.readline().split()])
sort_by_x = sorted([[i, j] for i,j in city_ls], key=lambda x:x[0])
sort_by_y = sorted([[j, i] for i,j in city_ls], key=lambda x:x[0])
G = []
id2pos = {i : tuple(j) for i, j in enumerate(city_ls)}
pos2id = {j : i for i, j in list(id2pos.items())}
for i in range(len(sort_by_x)-1):
    current_by_x = sort_by_x[i]
    next_by_x = sort_by_x[i + 1]
    G.append((abs(current_by_x[0] - next_by_x[0]),current_by_x, next_by_x))
sort_by_x.sort(key=lambda x:x[1])
for i in range(len(sort_by_x) - 1):
    current_by_x = sort_by_x[i]
    next_by_x = sort_by_x[i + 1]
    G.append((abs(current_by_x[1] - next_by_x[1]), current_by_x, next_by_x))
G.sort(key=lambda x:x[0])
sum_cost = 0
par = [i for i in range(N)]
rank = [1 for i in range(N)]
def find(x):
    if par[x] == x:
        return x
    else:
        return find(par[x])

def unite(x, y):
    x = find(x)
    y = find(y)
    if x == y:
        pass
    else:
        if rank[x] > rank[y]:
            par[y] = x
            rank[x] += rank[y]
        else:
            par[x] = par[y]
            rank[y] += rank[x]

def is_same(x, y):
    if find(x) == find(y):
        return True
    else:
        return False

for i in G:
    (cost, _from, _to) = i
    _from = pos2id[tuple(_from)]
    _to = pos2id[tuple(_to)]
    if is_same(_from, _to):
        continue
    unite(_from, _to)
    sum_cost += cost
print(sum_cost)

# Optimized solution
import sys
N = int(eval(input()))
city_ls = list()
for i in range(N):
    city_ls.append([int(i) for i in sys.stdin.readline().split()])
sort_by_x = sorted([[i, j] for i,j in city_ls], key=lambda x:x[0])
G = []
pos2id = {tuple(j) : i for i, j in enumerate(city_ls)}
for i in range(len(sort_by_x)-1):
    current_by_x = sort_by_x[i]
    next_by_x = sort_by_x[i + 1]
    G.append((abs(current_by_x[0] - next_by_x[0]),current_by_x, next_by_x))
sort_by_x.sort(key=lambda x:x[1])
for i in range(len(sort_by_x) - 1):
    current_by_x = sort_by_x[i]
    next_by_x = sort_by_x[i + 1]
    G.append((abs(current_by_x[1] - next_by_x[1]), current_by_x, next_by_x))
G.sort(key=lambda x:x[0])
sum_cost = 0
par = [i for i in range(N)]
rank = [1 for i in range(N)]
def find(x):
    if par[x] == x:
        return x
    else:
        return find(par[x])

def unite(x, y):
    x = find(x)
    y = find(y)
    if x == y:
        pass
    else:
        if rank[x] > rank[y]:
            par[y] = x
            rank[x] += rank[y]
        else:
            par[x] = par[y]
            rank[y] += rank[x]

def is_same(x, y):
    if find(x) == find(y):
        return True
    else:
        return False

for i in G:
    (cost, _from, _to) = i
    _from = pos2id[tuple(_from)]
    _to = pos2id[tuple(_to)]
    if is_same(_from, _to):
        continue
    unite(_from, _to)
    sum_cost += cost
print(sum_cost)
# Original solution
from sys import stdin
from collections import namedtuple
from heapq import heappush, heappop

input = stdin.readline


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

  def is_same(self, a, b):
    return self.find(a) == self.find(b)

  def unite(self, a, b):
    a = self.find(a)
    b = self.find(b)  
    if self.rank[a] < self.rank[b]:
      a, b = b, a
    self.par[b] = a
    if self.rank[a] == self.rank[b]:
      self.rank[a] += 1

  def find(self, a):
    if a == self.par[a]:
      return a
    self.par[a] = self.find(self.par[a])
    return self.par[a]

Edge = namedtuple('Edge', 'w s t')
X = namedtuple('X', 'x i')
Y = namedtuple('Y', 'y i')

N = int(eval(input()))

edges = []
xg = []
yg = []

for i in range(N):
  x, y = list(map(int, input().split()))
  xg.append(X(x, i))
  yg.append(Y(y, i))

xg.sort()
yg.sort()

for i in range(N - 1):
  x1, a = xg[i]
  x2, b = xg[i + 1]
  heappush(edges, Edge(abs(x1 - x2), a, b))

for i in range(N - 1):
  y1, a = yg[i]
  y2, b = yg[i + 1]
  heappush(edges, Edge(abs(y1 - y2), a, b))

u = UnionFind(N)
cost = 0

while edges:
  w, s, t = heappop(edges)
  if u.is_same(s, t):
    continue
  u.unite(s, t)
  cost += w

print(cost)


# Optimized solution
from collections import namedtuple


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

  def is_same(self, a, b):
    return self.find(a) == self.find(b)

  def unite(self, a, b):
    a = self.find(a)
    b = self.find(b)  
    if self.size[a] < self.size[b]:
      a, b = b, a
    self.par[b] = a
    self.size[a] += self.size[b]

  def size_of(self, a):
    return self.size[self.find(a)]

  def find(self, a):
    if a == self.par[a]:
      return a
    self.par[a] = self.find(self.par[a])
    return self.par[a]

Edge = namedtuple('Edge', 'w s t')
X = namedtuple('X', 'x i')
Y = namedtuple('Y', 'y i')

N = int(eval(input()))

edges = []
xg = []
yg = []

for i in range(N):
  x, y = list(map(int, input().split()))
  xg.append(X(x, i))
  yg.append(Y(y, i))

xg.sort()
yg.sort()

for i in range(N - 1):
  x1, a = xg[i]
  x2, b = xg[i + 1]
  edges.append(Edge(abs(x1 - x2), a, b))

for i in range(N - 1):
  y1, a = yg[i]
  y2, b = yg[i + 1]
  edges.append(Edge(abs(y1 - y2), a, b))

edges.sort()

u = UnionFind(N)
cost = 0

for w, s, t in edges:
  if u.is_same(s, t):
    continue
  u.unite(s, t)
  cost += w

print(cost)