import Data.List
import Data.Maybe
import Data.IntMap.Strict ((!))
import qualified Data.IntMap.Strict as M
import qualified Data.Set as S
import qualified Data.ByteString.Char8 as B

snub = S.toList . S.fromList
readInt = fst . fromJust . B.readInt
untilFix f x = if f x == x then x else untilFix f (f x)

kruskal edge = makepath M.empty 0 edge
  where
    makepath _ acc [] = acc
    makepath forest acc (((a,b),d):abd)
      | not p1 && not p2 = makepath forest1 (d+acc) abd
      | not p1 = makepath forest2 (d+acc) abd
      | not p2 = makepath forest3 (d+acc) abd
      | rep1 /= rep2 = makepath forest4 (d+acc) abd
      | otherwise = makepath forest acc abd
      where
        v1 = min a b
        v2 = max a b
        p1 = M.member v1 forest
        p2 = M.member v2 forest
        rep1 = untilFix (forest!) v1
        rep2 = untilFix (forest!) v2
        forest1 = M.insert v2 v1 (M.insert v1 v1 forest)
        forest2 = M.insert v1 rep2 forest
        forest3 = M.insert v2 rep1 forest
        forest4 = M.insert v2 rep1 (M.map (\v -> if v == rep2 then rep1 else v) forest)

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

built xysx xysy = kruskal edge
  where
    edge = sortOn snd (edgex ++ edgey)
    edgex = zipWith mkedge xysx (tail xysx)
    edgey = zipWith mkedge xysy (tail xysy)

mkedge ((xi,yi),i) ((xj,yj),j) = ((i,j), min (abs (xj-xi)) (abs (yj-yi)))
