use std::io::Read;

struct Edge {
    from: usize,
    to: usize,
    cost: i64,
}
impl Ord for Edge {
    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
        self.cost.cmp(&other.cost)
    }
}
impl PartialOrd for Edge {
    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
        Some(self.cost.cmp(&other.cost))
    }
}
impl Eq for Edge {}
impl PartialEq for Edge {
    fn eq(&self, other: &Self) -> bool {
        self.cost == other.cost
    }
}

struct UnionFind {
    parent: Vec<isize>,
}

impl UnionFind {
    fn new(size: usize) -> UnionFind {
        UnionFind {
            parent: vec![-1; size],
        }
    }
    fn find(&mut self, x: usize) -> usize {
        if self.parent[x] < 0 {
            x
        } else {
            self.find(self.parent[x] as usize)
        }
    }
    fn unite(&mut self, x: usize, y: usize) {
        let px = self.find(x);
        let py = self.find(y);
        if px == py {
            return;
        }
        if self.parent[px] < self.parent[py] {
            self.parent[px] += self.parent[py];
            self.parent[py] = px as isize;
        } else {
            self.parent[py] += self.parent[px];
            self.parent[px] = py as isize;
        }
    }
    fn same(&mut self, x: usize, y: usize) -> bool {
        self.find(x) == self.find(y)
    }
}

fn kruskal(edges: &mut Vec<Edge>) -> i64 {
    let n: usize = edges.len();
    edges.sort();

    let mut uf = UnionFind::new(n);
    let mut res: i64 = 0;
    for e in edges.iter() {
        if uf.same(e.from, e.to) {
            continue;
        }
        uf.unite(e.from, e.to);
        res += e.cost;
    }
    res
}

fn main() {
    let mut s = String::new();
    std::io::stdin().read_to_string(&mut s).ok();
    let mut itr = s.trim().split_whitespace();
    let n: usize = itr.next().unwrap().parse().unwrap();
    let mut xy: Vec<(i64, i64, usize)> = vec![];
    for i in 0..n {
        let x: i64 = itr.next().unwrap().parse().unwrap();
        let y: i64 = itr.next().unwrap().parse().unwrap();
        xy.push((x, y, i));
    }

    // make the graph
    let mut edges: Vec<Edge> = Vec::new();
    xy.sort_by(|a, b| a.0.cmp(&b.0));
    for i in 1..n {
        let (from_x, from_y, from_id) = xy[i - 1];
        let (to_x, to_y, to_id) = xy[i];
        let edge = Edge {
            from: from_id,
            to: to_id,
            cost: std::cmp::min((to_x - from_x).abs(), (to_y - from_y).abs()),
        };
        edges.push(edge);
    }

    xy.sort_by(|a, b| a.1.cmp(&b.1));
    for i in 1..n {
        let (from_x, from_y, from_id) = xy[i - 1];
        let (to_x, to_y, to_id) = xy[i];
        let edge = Edge {
            from: from_id,
            to: to_id,
            cost: std::cmp::min((to_x - from_x).abs(), (to_y - from_y).abs()),
        };
        edges.push(edge);
    }
    println!("{}", kruskal(&mut edges));
}