import Data.List
import Data.Maybe
import Control.Monad
import Data.Array.IO
import qualified Data.Set as S
import qualified Data.ByteString.Char8 as B

kruskalIO (n,edge) = do
 forest <- newListArray (0,n-1) [0..n-1] :: IO (IOUArray Int Int)
 rank <- newArray (0,n-1) 1 :: IO (IOUArray Int Int)
 ret <- foldM makepath ((forest,rank),0) edge
 return ret

makepath ((forest,rank),acc) ((a,b),d) = do
 rep1 <- untilFixM (readArray forest) a
 rank1 <- readArray rank rep1
 rep2 <- untilFixM (readArray forest) b
 rank2 <- readArray rank rep2
 if rep1 /= rep2
  then if rank1 >= rank2
   then do
    writeArray forest rep2 rep1
    writeArray forest b rep1
    writeArray rank rep1 (rank1+rank2)
    return ((forest,rank), acc+d)
   else do
    writeArray forest rep1 rep2
    writeArray forest a rep2
    writeArray rank rep2 (rank1+rank2)
    return ((forest,rank), acc+d)    
  else do
   return ((forest,rank), acc)

main = do
 getLine
 xys <- intPairs <$> B.getContents
 ret <- snd <$> kruskalIO (mkedge xys)
 print ret

mkedge xys = (n,edge)
 where
  xyis = zip (snub xys) [0..]
  n = length xyis
  xysx = sortOn fst xyis
  xysy = sortOn (snd.fst) xyis
  edgex = zipWith make xysx (tail xysx)
  edgey = zipWith make xysy (tail xysy)
  edge = sortOn snd (edgex ++ edgey)

make ((xi,yi),i) ((xj,yj),j) = ((a,b),d)
 where
  a = min i j
  b = max i j
  d = min (abs (xj-xi)) (abs (yj-yi))

snub = S.toList . S.fromList
intPairs = map ((\[x,y]->(x,y)) . map (fst . fromJust . B.readInt) . B.words) . B.lines
untilFixM f x0 = f x0 >>= \x -> if x == x0 then return x else untilFixM f x