import Data.List
import qualified Data.Set as S
import qualified Data.Map as M
import qualified Data.IntMap as IM
import qualified Data.ByteString.Char8 as B

snub = S.toList . S.fromList

readInt = maybe undefined fst . B.readInt

untilFix f x = let x1 = f x in if x1 == x then x else untilFix f x1

kruskal n = kruskalDP n initial 0 0

kruskalDP _ _ acc _ [] = acc
kruskalDP n uf acc x ((d,(a,b)):abd)
  | x == n - 1 = acc
  | same uf a b = kruskalDP n uf acc x abd
  | otherwise = kruskalDP n (merge uf a b) (acc + d) (x + 1) abd

main = do
  _ <- getLine
  xys <- map ((\[x,y]->(x+1,y+1)) . map readInt . B.words) . B.lines <$> B.getContents
  let xyis = zip (snub xys) [1 ..]
  let n = length xyis
  let xysx = xyis
  let xysy = sortOn (snd.fst) xyis
  print (built n xysx xysy)

built n xysx xysy = kruskal n edge
  where
    edge = sort (edgex ++ edgey)
    edgex = zipWith (\((xi,yi),i) ((xj,yj),j) -> (min (abs (xj-xi)) (abs (yj-yi)), (i,j))) xysx (tail xysx)
    edgey = zipWith (\((xi,yi),i) ((xj,yj),j) -> (min (abs (yj-yi)) (abs (xj-xi)), (i,j))) xysy (tail xysy)

data UnionFind = UnionFind {tree :: IM.IntMap Point, rk :: IM.IntMap Rank}
type Point = Int
type Rank = Int

initial :: UnionFind
initial = UnionFind (IM.singleton 0 0) IM.empty

(!?) :: UnionFind -> Point -> Point
(!?) uf p = IM.findWithDefault 0 p (tree uf)

rep :: UnionFind -> Point -> Point
rep uf = untilFix (uf !?)

rank :: UnionFind -> Point -> Rank
rank uf = (rk uf IM.!)

isolate :: UnionFind -> Point -> Bool
isolate uf p = rep uf p == 0

merge :: UnionFind -> Point -> Point -> UnionFind
merge uf p1 p2
  | i1 && i2 = UnionFind (IM.insert p2 p1 (IM.insert p1 p1 (tree uf))) (IM.insert p1 2 (rk uf))
  | i1 = UnionFind (IM.insert p1 rp2 (tree uf)) (IM.insert rp2 (rk2 + 1) (rk uf))
  | i2 = UnionFind (IM.insert p2 rp1 (tree uf)) (IM.insert rp1 (rk1 + 1) (rk uf))
  | rp1 /= rp2 && rk1 > rk2 = UnionFind (IM.insert p2 rp1 (IM.insert rp2 rp1 (tree uf))) (IM.insert rp1 (rk1 + rk2) (rk uf))
  | rp1 /= rp2 = UnionFind (IM.insert p1 rp2 (IM.insert rp1 rp2 (tree uf))) (IM.insert rp2 (rk1 + rk2) (rk uf))
  | otherwise = uf
  where
    i1 = isolate uf p1
    i2 = isolate uf p2
    rk1 = rank uf rp1
    rk2 = rank uf rp2
    rp1 = rep uf p1
    rp2 = rep uf p2

same :: UnionFind -> Point -> Point -> Bool
same uf p1 p2
  | p1 == p2 = True
  | otherwise = not (isolate uf p1) && (rep uf p1 == rep uf p2)
