グラフ - 最小全域木 - クラスカル法

概要

辺ベースに最小の辺を足してくアルゴリズム. 計算量は \(O(E \log E)\).

/// Graph - Minimal Spanning Tree - Kruskal Algorithm
use crate::algebra::group::*;
use crate::set::union_find::*;

pub fn kruskal<Cost: Copy + Group + Ord>(neigh: &Vec<Vec<(usize, Cost)>>) -> Cost {
    let n = neigh.len();
    let mut total = Cost::zero();
    let mut uf = UnionFind::new(n);
    let mut q = vec![];
    for u in 0..n {
        for &(v, cost) in neigh[u].iter() {
            q.push((cost, u, v));
        }
    }
    q.sort();
    for &(cost, i, j) in q.iter() {
        if uf.is_same(i, j) {
            continue;
        }
        uf.merge(i, j);
        total = total + cost;
    }
    total
}

#[cfg(test)]
mod test_kruskal {
    use crate::graph::minimal_span_tree::kruskal::*;

    fn undirectize<Cost: Copy>(g: &Vec<Vec<(usize, Cost)>>) -> Vec<Vec<(usize, Cost)>> {
        let n = g.len();
        let mut h = vec![vec![]; n];
        for u in 0..n {
            for &(v, cost) in g[u].iter() {
                h[u].push((v, cost));
                h[v].push((u, cost));
            }
        }
        h
    }

    #[test]
    fn it_works() {
        assert_eq!(
            kruskal(&undirectize(&vec![
                vec![(1, 7), (3, 5)],
                vec![(2, 8), (3, 9), (4, 7)],
                vec![(4, 5)],
                vec![(4, 15), (5, 6)],
                vec![(5, 8), (6, 9)],
                vec![(6, 11)],
                vec![],
            ])),
            39
        );
    }
}