import Data.List
import Data.Maybe
import Data.IntMap ((!))
import qualified Data.IntMap as M
import qualified Data.Set as S
import qualified Data.ByteString.Char8 as B
 
_nub = S.toList . S.fromList
readInt = fst . fromJust . B.readInt
untilFix f x = if f x == x then x else untilFix f (f x)

kruskal n edge = makepath uft 0 edge
 where
  uft = M.fromDistinctAscList (zip [1..n] [1..])
  makepath _ acc [] = acc
  makepath forest acc (((a,b),d):abd)
   | rep1 /= rep2 = makepath _forest (d+acc) abd
   | otherwise = makepath forest acc abd
   where
    rep1 = untilFix (forest!) a
    rep2 = untilFix (forest!) b
    _forest = M.insert b rep1 (M.insert rep2 rep1 forest)
    
main = do
 getLine
 xys <- map (map readInt . B.words) . B.lines <$> B.getContents
 let xyis = zip (_nub xys) [1..]
 let _n = length xyis
 let xysx = sortOn (head.fst) xyis
 let xysy = sortOn (last.fst) xyis
 print (built _n xysx xysy)

built n xysx xysy = kruskal n edge
 where
  edge = sortOn snd (edgex ++ edgey)
  edgex = zipWith mkedgex xysx (tail xysx)
  edgey = zipWith mkedgey xysy (tail xysy)
  mkedgex ([xi,_],i) ([xj,_],j) = ((min i j, max i j), xj-xi)
  mkedgey ([_,yi],i) ([_,yj],j) = ((min i j, max i j), yj-yi)