import Data.Array.IO
import Data.List
import Control.Monad

type UnionFindIO = IOArray Int Int

newUFIO :: Int -> IO UnionFindIO
newUFIO n = newListArray (1,n) [1..n]

findUFIO :: Int -> UnionFindIO -> IO Int
findUFIO x uf = do
  parent <- readArray uf x
  if parent == x then
    return x
    else do
    next <- findUFIO parent uf
    writeArray uf x next
    return next

sameUFIO :: Int -> Int -> UnionFindIO -> IO Bool
sameUFIO x y uf = do
  xx <- findUFIO x uf
  yy <- findUFIO y uf
  return $ xx == yy

unionUFIO :: Int -> Int -> UnionFindIO -> IO ()
unionUFIO x y uf = do
  xx <- findUFIO x uf
  yy <- findUFIO y uf

  if xx == yy then
    return ()
    else
    writeArray uf x y


type City = (Int,(Int,Int))

kruskal :: [City] -> [(City,City)] -> IO Int
kruskal nodes edges = do
  let sorted = sortBy comp edges

  uf <- newUFIO (length nodes)

  let
    kruskal' [] = return []
    kruskal' (e@((i,(xi,yi)),(j,(xj,yj))):es) = do
      same <- sameUFIO i j uf
      if same then
        kruskal' es
        else do
        unionUFIO i j uf
        kruskal' es >>= \list -> return $ e : list
        
  kruskal' sorted >>= return . sum . map dist
  where
    comp e1 e2 = compare (dist e1) (dist e2)
    dist ((_,(x1,y1)), (_,(x2,y2))) = min (abs $ x1-x2) (abs $ y1-y2)

listToTuple2 (a:b:_) = (a,b)

main = do
  n <- readLn :: IO Int
  nodes <- getContents >>= return . zip [1..] . map (listToTuple2 . map read . words) . lines :: IO [(Int,(Int,Int))]
  let roads = f (sortBy (\(_,(x1,y1)) (_,(x2,y2)) -> compare x1 x2) nodes) ++
              f (sortBy (\(_,(x1,y1)) (_,(x2,y2)) -> compare y1 y2) nodes)

  print =<< kruskal nodes roads

  where
    f (_:[]) = []
    f (x:y:xs) = (x,y) : f (y:xs)
