CodeEff/ECCO huggingface dataset:
# Original solution
class UnionFind(object):
  def __init__(self, n=1):
    self.par = [i for i in range(n)]
    self.rank = [0 for _ in range(n)]
    self.size = [1 for _ in range(n)]
  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:
      if self.rank[x] < self.rank[y]:
        x, y = y, x
      if self.rank[x] == self.rank[y]:
        self.rank[x] += 1
      self.par[y] = x
      self.size[x] += self.size[y]
  def is_same(self, x, y):
    return self.find(x) == self.find(y)
  def get_size(self, x):
    x = self.find(x)
    return self.size[x]


from heapq import heapify, heappop, heappush

N = int(eval(input()))
X = []; Y = []
for i in range(N):
  x,y = list(map(int,input().split()))
  X.append((x,i));Y.append((y,i))
X.sort();Y.sort()
dx = [];dy =[]
for i in range(N-1):
  tx = X[i+1][0]-X[i][0]
  dx.append((tx,(X[i+1][1],X[i][1])))
  ty = Y[i+1][0]-Y[i][0]
  dy.append((ty,(Y[i+1][1],Y[i][1])))
heapify(dx);heapify(dy)
#print(dx,dy)
visited = set([])
ans = 0
uf = UnionFind(N)
while uf.get_size(0) < N:
  if not dy or dx[0] <= dy[0]:
    cost, loc = heappop(dx)
  else:
    cost, loc = heappop(dy)
  if uf.is_same(loc[0],loc[1]): #すでに接続済みのところはスキップ
    continue
  ans += cost
  #print(cost)
  uf.union(loc[0],loc[1])
print(ans)

# Optimized solution
class UnionFind(object):
  def __init__(self, n=1):
    self.par = [i for i in range(n)]
    self.rank = [0 for _ in range(n)]
    self.size = [1 for _ in range(n)]
  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:
      if self.rank[x] < self.rank[y]:
        x, y = y, x
      if self.rank[x] == self.rank[y]:
        self.rank[x] += 1
      self.par[y] = x
      self.size[x] += self.size[y]
  def is_same(self, x, y):
    return self.find(x) == self.find(y)
  def get_size(self, x):
    x = self.find(x)
    return self.size[x]

import sys
input = sys.stdin.readline

from heapq import heapify, heappop, heappush

N = int(eval(input()))
X = []; Y = []
for i in range(N):
  x,y = list(map(int,input().split()))
  X.append((x,i));Y.append((y,i))
X.sort();Y.sort()
dx = [];dy =[]
for i in range(N-1):
  tx = X[i+1][0]-X[i][0]
  dx.append((tx,(X[i+1][1],X[i][1])))
  ty = Y[i+1][0]-Y[i][0]
  dy.append((ty,(Y[i+1][1],Y[i][1])))
heapify(dx);heapify(dy)
#print(dx,dy)
visited = set([])
ans = 0
uf = UnionFind(N)
while uf.get_size(0) < N:
  if not dy or dx[0] <= dy[0]:
    cost, loc = heappop(dx)
  else:
    cost, loc = heappop(dy)
  if uf.is_same(loc[0],loc[1]): #すでに接続済みのところはスキップ
    continue
  ans += cost
  #print(cost)
  uf.union(loc[0],loc[1])
print(ans)
# Original solution
class UnionFind(object):
  def __init__(self, n=1):
    self.par = [i for i in range(n)]
    self.rank = [0 for _ in range(n)]
    self.size = [1 for _ in range(n)]
  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:
      if self.rank[x] < self.rank[y]:
        x, y = y, x
      if self.rank[x] == self.rank[y]:
        self.rank[x] += 1
      self.par[y] = x
      self.size[x] += self.size[y]
  def is_same(self, x, y):
    return self.find(x) == self.find(y)
  def get_size(self, x):
    x = self.find(x)
    return self.size[x]

import sys
input = sys.stdin.readline

from heapq import heapify, heappop, heappush

N = int(eval(input()))
X = []; Y = []
for i in range(N):
  x,y = list(map(int,input().split()))
  X.append((x,i));Y.append((y,i))
X.sort();Y.sort()
dx = [];dy =[]
for i in range(N-1):
  tx = X[i+1][0]-X[i][0]
  dx.append((tx,(X[i+1][1],X[i][1])))
  ty = Y[i+1][0]-Y[i][0]
  dy.append((ty,(Y[i+1][1],Y[i][1])))
heapify(dx);heapify(dy)
#print(dx,dy)
visited = set([])
ans = 0
uf = UnionFind(N)
while uf.get_size(0) < N:
  if not dy or dx[0] <= dy[0]:
    cost, loc = heappop(dx)
  else:
    cost, loc = heappop(dy)
  if uf.is_same(loc[0],loc[1]): #すでに接続済みのところはスキップ
    continue
  ans += cost
  #print(cost)
  uf.union(loc[0],loc[1])
print(ans)

# Optimized solution
class UnionFind(object):
    def __init__(self, n=1):
        self.par = [i for i in range(n)]
        self.rank = [0 for _ in range(n)]
        self.size = [1 for _ in range(n)]
    def find(self, x):
        """
        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 と y のグループを結合
        """
        x = self.find(x)
        y = self.find(y)
        if x != y:
            if self.rank[x] < self.rank[y]:
                x, y = y, x
            if self.rank[x] == self.rank[y]:
                self.rank[x] += 1
            self.par[y] = x
            self.size[x] += self.size[y]
    def is_same(self, x, y):
        """
        x と y が同じグループか否か
        """
        return self.find(x) == self.find(y)
    def get_size(self, x):
        """
        x が属するグループの要素数
        """
        x = self.find(x)
        return self.size[x]

from heapq import heapify, heappop, heappush
N = int(eval(input()))
X = [];Y = []
for i in range(N):
  a,b = list(map(int,input().split()))
  X.append((a,b,i))
  Y.append((a,b,i))
X.sort(key=lambda x:x[0])
Y.sort(key=lambda x:x[1])
#print(X,Y)
PQ = []
for i in range(N-1):
  difx = (X[i+1][0]-X[i][0],X[i][2],X[i+1][2])
  dify = (Y[i+1][1]-Y[i][1],Y[i][2],Y[i+1][2])
  #print(difx,dify)
  heappush(PQ,difx);heappush(PQ,dify)
uf = UnionFind(N)
ans = 0
while PQ:
  dis,a,b = heappop(PQ)
  if uf.is_same(a, b):
    continue
  ans += dis
  uf.union(a,b)
print(ans)
# Original solution
import heapq
import sys
sys.setrecursionlimit(10**9)
input=sys.stdin.readline

N=int(eval(input()))

xylist,yxlist=[],[]
par_dic={}
for i in range(N):
  x,y=list(map(int,input().split()))
  xylist.append((x,y))
  yxlist.append((y,x))
  par_dic[(x,y)]=(x,y)
xylist.sort()
yxlist.sort()
#print(xylist)

hq=[]
for i in range(1,N):
  x1,y1=xylist[i-1]
  x2,y2=xylist[i]
  heapq.heappush(hq,(min(abs(x2-x1),abs(y1-y2)),(x1,y1),(x2,y2)))
  y1,x1=yxlist[i-1]
  y2,x2=yxlist[i]
  heapq.heappush(hq,(min(abs(x2-x1),abs(y1-y2)),(x1,y1),(x2,y2)))
#print(hq)

def get_par(x):
  if x == par_dic[x]:
    return x
  else:
    par_dic[x] = get_par(par_dic[x])
    return par_dic[x]
def merge(x,y):
  par_x = get_par(x)
  par_y = get_par(y)
  if par_x != par_y:
    par_dic[par_y] = par_x
def is_same(x,y):
  return get_par(x) == get_par(y)

answer=0
while hq:
  d,p1,p2=heapq.heappop(hq)
  #print(d,p1,p2)
  if not is_same(p1,p2):
    merge(p1,p2)
    answer+=d
  
print(answer)

# Optimized solution
import sys
sys.setrecursionlimit(10**9)
input=sys.stdin.readline

N=int(eval(input()))

xylist,yxlist=[],[]
par_dic={}
for i in range(N):
  x,y=list(map(int,input().split()))
  xylist.append((x,y))
  yxlist.append((y,x))
  par_dic[(x,y)]=(x,y)
xylist.sort()
yxlist.sort()
#print(xylist)

elist=[]
for i in range(1,N):
  x1,y1=xylist[i-1]
  x2,y2=xylist[i]
  elist.append((min(abs(x2-x1),abs(y1-y2)),(x1,y1),(x2,y2)))
  y1,x1=yxlist[i-1]
  y2,x2=yxlist[i]
  elist.append((min(abs(x2-x1),abs(y1-y2)),(x1,y1),(x2,y2)))
#print(hq)
elist.sort(reverse=True)

def get_par(x):
  if x == par_dic[x]:
    return x
  else:
    par_dic[x] = get_par(par_dic[x])
    return par_dic[x]
def merge(x,y):
  par_x = get_par(x)
  par_y = get_par(y)
  if par_x != par_y:
    par_dic[par_y] = par_x
def is_same(x,y):
  return get_par(x) == get_par(y)

answer=0
while elist:
  d,p1,p2=elist.pop()
  #print(d,p1,p2)
  if not is_same(p1,p2):
    merge(p1,p2)
    answer+=d
  
print(answer)
# Original solution
import sys
import heapq
input = sys.stdin.readline

N = int(eval(input()))
cityx = []
cityy = []
for i in range(N):
    x,y = list(map(int,input().split()))
    cityx.append([x,i])
    cityy.append([y,i])
cityx.sort()
cityy.sort()

side = [[]for i in range(N)]
for i in range(N-1):
    a,x = cityx[i]
    b,y = cityx[i+1]
    side[x].append([b-a,y])
    side[y].append([b-a,x])
for i in range(N-1):
    a,x = cityy[i]
    b,y = cityy[i+1]
    side[x].append([b-a,y])
    side[y].append([b-a,x])

f = [1] + [0] * (N-1)
queue = side[0][:]
ans = 0
heapq.heapify(queue)
while queue:
    cost, q = heapq.heappop(queue)
    if f[q] == 0:
        ans += cost
        f[q] = 1
        for a,b in side[q]:
            heapq.heappush(queue,[a,b])

print(ans)

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

N = int(eval(input()))
cityx = [[0,i]for i in range(N)]
cityy = [[0,i]for i in range(N)]
for i in range(N):
    x,y = list(map(int,input().split()))
    cityx[i][0] = x
    cityy[i][0] = y

cityx.sort()
cityy.sort()
side = []
for i in range(N-1):
    side.append([cityx[i+1][0]-cityx[i][0], cityx[i+1][1], cityx[i][1]])
    side.append([cityy[i+1][0]-cityy[i][0], cityy[i+1][1], cityy[i][1]])
side.sort()
ans = 0
per = [i for i in range(N)]
rank = [0]*N
def find(x):
    if per[x] == x:
        return x
    else:
        per[x] = find(per[x])
        return per[x]

ans = 0

for cost,x,y in side:
    x = find(x)
    y = find(y)
    if x != y:
        ans += cost
        if rank[x] < rank[y]:
            per[x] = y
        else:
            per[y] = x
            if rank[x] == rank[y]:
                rank[x] += 1

print(ans)
# Original solution
n=int(eval(input()))
import heapq
hqx=[]
hqy=[]
for i in range(n):
    x,y=list(map(int,input().split()))
    heapq.heappush(hqx,(x,i))
    heapq.heappush(hqy,(y,i))
prex,prexi=heapq.heappop(hqx)
prey,preyi=heapq.heappop(hqy)
edges=[]#(cost,v1,v2)
for i in range(n-1):
    x,xi=heapq.heappop(hqx)
    y,yi=heapq.heappop(hqy)
    heapq.heappush(edges,(x-prex,prexi,xi))
    heapq.heappush(edges,(y-prey,preyi,yi))
    prex,prexi=x,xi
    prey,preyi=y,yi

frag=list(range(n+1))
fragnum=[0]*(n+1)

#以下でフラグ建設 フラグが同じなら同じチームである
def takefrag(p):
    stock=[]
    while frag[frag[p]]!=frag[p]:
        stock.append(p)
        p=frag[p]
    p=frag[p]
    for i in stock:
        frag[i]=p
    return p

count=0
ans=0
while True:
    cost,a,b=heapq.heappop(edges)
    f1,f2 = list(map(takefrag,(a,b)))
    if f1!=f2:
        count+=1
        f1,f2 = min(f1,f2),max(f1,f2)
        frag[f1]=f2
        ans+=cost
    if count==n-1:
        break

print(ans)

# Optimized solution
n=int(eval(input()))
hqx=[]
hqy=[]
for i in range(n):
    x,y=list(map(int,input().split()))
    hqx.append((x,i))
    hqy.append((y,i))
hqx.sort()
hqy.sort()
prex,prexi=hqx[0]
prey,preyi=hqy[0]
edges=[]#(cost,v1,v2)
for i in range(1,n):
    x,xi=hqx[i]
    y,yi=hqy[i]
    edges.append((x-prex,prexi,xi))
    edges.append((y-prey,preyi,yi))
    prex,prexi=x,xi
    prey,preyi=y,yi
edges.sort()

frag=list(range(n+1))
fragnum=[0]*(n+1)

def takefrag(p):
    stock=[]
    while frag[frag[p]]!=frag[p]:
        stock.append(p)
        p=frag[p]
    p=frag[p]
    for i in stock:
        frag[i]=p
    return p

count=0
ans=0
for i in range(2*n):
    cost,a,b=edges[i]
    f1,f2 = list(map(takefrag,(a,b)))
    if f1!=f2:
        count+=1
        f1,f2 = min(f1,f2),max(f1,f2)
        frag[f1]=f2
        ans+=cost
    if count==n-1:
        break

print(ans)
# Original solution
import heapq
def prim_heap():
    used = [True] * n #True:不使用
    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

#########################
n= int(eval(input()))

edge = [[] for i in range(n)]
#隣接リスト edge[i]:[コスト,行先]
l=[]
for i in range(n):
    a,b=list(map(int,input().split()))
    l.append([a,b,i])
l=sorted(l,key=lambda x: -x[0])
for i in range(n-1):
    x=l[i][2]
    y=l[i+1][2]
    z=l[i][0]-l[i+1][0]
    edge[x].append([z,y])
    edge[y].append([z,x])
l=sorted(l,key=lambda x: -x[1])
for i in range(n-1):
    x=l[i][2]
    y=l[i+1][2]
    z=l[i][1]-l[i+1][1]
    edge[x].append([z,y])
    edge[y].append([z,x])
print((prim_heap()))


# Optimized solution
import heapq
import sys
input = sys.stdin.readline
def prim_heap():
    used = [True] * n #True:不使用
    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

#########################
n= int(eval(input()))

edge = [[] for i in range(n)]
#隣接リスト edge[i]:[コスト,行先]
l=[]
for i in range(n):
    a,b=list(map(int,input().split()))
    l.append([a,b,i])
l=sorted(l,key=lambda x: -x[0])
for i in range(n-1):
    x=l[i][2]
    y=l[i+1][2]
    z=l[i][0]-l[i+1][0]
    edge[x].append([z,y])
    edge[y].append([z,x])
l=sorted(l,key=lambda x: -x[1])
for i in range(n-1):
    x=l[i][2]
    y=l[i+1][2]
    z=l[i][1]-l[i+1][1]
    edge[x].append([z,y])
    edge[y].append([z,x])
print((prim_heap()))
# Original solution
import heapq as hq
class UnionFind(object):
    def __init__(self, size):
        self.parent = [i for i in range(size)]
        self.rank = [0]*size
    def find(self, x):
        if self.parent[x] == x:
            return x
        self.parent[x] = self.find(self.parent[x])
        return self.parent[x]
    def unite(self, x, y):
        x, y = self.find(x), self.find(y)
        if x == y:
            return
        if self.rank[x] < self.rank[y]:
            self.parent[x] = y
        else:
            self.parent[y] = x
            if self.rank[x] == self.rank[y]:
                self.rank[x] += 1
    def same(self, x, y):
        return self.find(x) == self.find(y)
N = int(eval(input()))
ls = []
rs = []
ind = 0
inds = dict()
for _ in range(N):
    x,y = list(map(int,input().split()))
    if (x,y) not in list(inds.keys()):
        ls.append((x,y))
        rs.append((y,x))
        inds[(x,y)] = ind
        ind += 1
N = ind
ls.sort()
rs.sort()
uf = UnionFind(N)

edges = []
for i in range(N-1):
    x = ls[i][0]
    a = ls[i+1][0]
    y = ls[i][1]
    b = ls[i+1][1]
    d = min(abs(x-a), abs(y-b))
    edges.append((d,(x,y),(a,b)))
    x = rs[i][1]
    a = rs[i+1][1]
    y = rs[i][0]
    b = rs[i+1][0]
    d = min(abs(x-a), abs(y-b))
    edges.append((d,(x,y),(a,b)))
edges.sort(key=lambda x:x[0])
ans = 0
for d,i,j in edges:
        # 閉路ができない場合追加する
        if not uf.same(inds[i],inds[j]):
            uf.unite(inds[i],inds[j])
            ans += d
print(ans)

# Optimized solution
import sys
input = sys.stdin.readline
class UnionFind(object):
    def __init__(self, size):
        self.parent = [i for i in range(size)]
        self.rank = [0]*size
    def find(self, x):
        if self.parent[x] == x:
            return x
        # path compression
        self.parent[x] = self.find(self.parent[x])
        return self.parent[x]
    
    def unite(self, x, y):
        x, y = self.find(x), self.find(y)
        if x == y:
            return
        # union by rank
        if self.rank[x] < self.rank[y]:
            self.parent[x] = y
        else:
            self.parent[y] = x
            if self.rank[x] == self.rank[y]:
                self.rank[x] += 1
    
    def same(self, x, y):
        return self.find(x) == self.find(y)

if __name__ == "__main__":
    N = int(eval(input()))
    vs = []
    for i in range(N):
        x,y = list(map(int,input().split()))
        vs.append((x,y,i))
    vs.sort()
    edges = []
    for k in range(1, N):
        x,y,i = vs[k]
        a,b,j = vs[k-1]
        edges.append((i, j, min(abs(x-a),abs(y-b))))
    vs.sort(key=lambda x:x[1])
    for k in range(1, N):
        x,y,i = vs[k]
        a,b,j = vs[k-1]
        edges.append((i, j, min(abs(x-a),abs(y-b))))
    uf = UnionFind(N)
    edges.sort(key=lambda x:x[2])
    ans = 0
    for i,j,w in edges:
        if not uf.same(i,j):
            uf.unite(i,j)
            ans += w
    print(ans)
# Original solution
import array
import collections
import heapq

AdjacentVertex = collections.namedtuple("AdjacentVertex", "vertex cost")
INF = 2 ** 31 - 1
NO_VERTEX = -1


# Prim法で頂点0からの最小全域木を求める
def compute_mst_prim(max_v, adj_list):
    # pred[u]は頂点uの「ひとつ前」の頂点を表す
    pred = collections.defaultdict(lambda: NO_VERTEX)
    # uとpred[u]を結ぶ辺の重みがkey[u]に入る
    key = collections.defaultdict(lambda: INF)
    key[0] = 0
    # 二分ヒープを優先度付きキューとして用いる
    pq = [(key[v], v) for v in range(max_v)]
    heapq.heapify(pq)
    # 優先度付きキューに頂点が入っているかを示す配列
    in_pq = array.array("B", (True for _ in range(max_v)))
    while pq:
        _, u = heapq.heappop(pq)
        in_pq[u] = False
        for v, v_cost in adj_list[u]:
            if in_pq[v]:
                weight = v_cost
                if weight < key[v]:
                    pred[v] = u
                    key[v] = weight
                    heapq.heappush(pq, (weight, v))
                    in_pq[v] = True
    return (pred, key)


def main():
    n = int(eval(input()))
    z = []
    for i in range(n):  # h:高さ
        z.append([int(m) for m in input().split()] + [i])

    zx = sorted(z, key=lambda x: (x[0]))
    zy = sorted(z, key=lambda x: (x[1]))

    # 最小木問題をプリム法で解く

    # 点群を発生
    p = [[zx[i][2], zx[i + 1][2], min(abs(zx[i][0] - zx[i + 1][0]), abs(zx[i][1] - zx[i + 1][1]))] for i in range(n - 1)]
    p += [[zy[i][2], zy[i + 1][2], min(abs(zy[i][0] - zy[i + 1][0]), abs(zy[i][1] - zy[i + 1][1]))] for i in range(n - 1)]

    max_v, max_e = n, len(p)
    adjacency_list = collections.defaultdict(set)
    for i in range(max_e):
        s, t, w = p[i][0], p[i][1], p[i][2]
        adjacency_list[s].add(AdjacentVertex(t, w))
        adjacency_list[t].add(AdjacentVertex(s, w))
    (_, key) = compute_mst_prim(max_v, adjacency_list)
    print((sum(key.values())))


if __name__ == '__main__':
    main()

# Optimized solution
N = int(eval(input()))

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

# x, y座標の値でソートして、隣接する街の間の道を、隣接リストadjに追加する
adj = [[] for i in range(N)]
for xy in [1, 2]:
    towns.sort(key=lambda t: t[xy])
    for i in range(N - 1):
        t1 = towns[i][0]
        t2 = towns[i + 1][0]
        cost = min(abs(towns[i + 1][1] - towns[i][1]), abs(towns[i + 1][2] - towns[i][2]))#towns[i + 1][xy] - towns[i][xy]
        adj[t1].append((t2, cost))
        adj[t2].append((t1, cost))

# 最小全域木を求める（プリム法）
import heapq
pq = []
heapq.heappush(pq, (0, 0))

done = set()
ans = 0
while pq:
    cost, v_now = heapq.heappop(pq)

    if v_now in done:
        continue

    ans += cost
    done.add(v_now)

    if len(done) == N:
        break

    for v, c in adj[v_now]:
        if v not in done:
            heapq.heappush(pq, (c, v))

print(ans)
# Original solution
def main():
    import sys 
    input = sys.stdin.readline
    from heapq import heappop,heappush
    from operator import itemgetter
    
    def prim():
        used = [True]*n
        edgelist = []
        for e in edge[0]:
            heappush(edgelist,e)
        used[0] = False
        res = 0
        while len(edgelist) != 0:
            short_edge = heappop(edgelist)
            if not used[short_edge[1]]:
                continue
            v = short_edge[1]
            used[v] = False
            for e in edge[v]:
                if used[e[1]]:
                    heappush(edgelist,e)
            res += short_edge[0]
        return res

    n = int(eval(input()))
    A = [list(map(int,input().split()))+[i] for i in range(n)]
    A.append([-10**12,-10**12,-1])
    A.append([10**12,10**12,-1])
    X = sorted(A)
    Y = sorted(A,key = itemgetter(1))
    d = []
    dapp = d.append
    for i in range(1,n+1):
        sx = X[i-1][0]
        sy = Y[i-1][1]
        mx = X[i][0]
        my = Y[i][1]
        lx = X[i+1][0]
        ly = Y[i+1][1]
        nsx = X[i-1][2]
        nsy = Y[i-1][2]
        nmx = X[i][2]
        nmy = Y[i][2]
        nlx = X[i+1][2]
        nly = Y[i+1][2]
        dapp((nsx,nmx,mx-sx))
        dapp((nmx,nlx,lx-mx))
        dapp((nsy,nmy,my-sy))
        dapp((nmy,nly,ly-my))

    edge = [[] for i in range(n)]
    for x,y,z in d:
        if x==-1 or y==-1:
            continue
        edge[x].append([z,y])
        edge[y].append([z,x])

    print((prim())) 

if __name__ == '__main__':
    main()

# Optimized solution
def main():
    import sys 
    input = sys.stdin.readline
    from heapq import heappop,heappush
    from operator import itemgetter
    
    def prim():
        used = [True]*n
        edgelist = []
        for e in edge[0]:
            heappush(edgelist,e)
        used[0] = False
        res = 0
        while len(edgelist) != 0:
            short_edge = heappop(edgelist)
            if not used[short_edge[1]]:
                continue
            v = short_edge[1]
            used[v] = False
            for e in edge[v]:
                if used[e[1]]:
                    heappush(edgelist,e)
            res += short_edge[0]
        return res

    n = int(eval(input()))
    A = [list(map(int,input().split()))+[i] for i in range(n)]
    A.append([-10**12,-10**12,-1])
    A.append([10**12,10**12,-1])
    X = sorted(A)
    Y = sorted(A,key = itemgetter(1))
    edge = [[] for i in range(n)]
    for i in range(1,n+1):
        sx = X[i-1][0]
        sy = Y[i-1][1]
        mx = X[i][0]
        my = Y[i][1]
        lx = X[i+1][0]
        ly = Y[i+1][1]
        nsx = X[i-1][2]
        nsy = Y[i-1][2]
        nmx = X[i][2]
        nmy = Y[i][2]
        nlx = X[i+1][2]
        nly = Y[i+1][2]
        edge[nsx].append((mx-sx,nmx))
        edge[nmx].append((mx-sx,nsx))
        edge[nlx].append((lx-mx,nmx))
        edge[nmx].append((lx-mx,nlx))
        edge[nsy].append((my-sy,nmy))
        edge[nmy].append((my-sy,nsy))
        edge[nly].append((ly-my,nmy))
        edge[nmy].append((ly-my,nly))

    print((prim())) 

if __name__ == '__main__':
    main()