Problem:
Minimum Spanning Tree

Find the sum of weights of edges of the Minimum Spanning Tree for a given weighted undirected graph G = (V, E).

Input

|V| |E|
s0 t0 w0
s1 t1 w1
:
s|E|-1 t|E|-1 w|E|-1

, where |V| is the number of vertices and |E| is the number of edges in the graph. The graph vertices are named with the numbers 0, 1,..., |V|-1 respectively.

si and ti represent source and target verticess of i-th edge (undirected) and wi represents the weight of the i-th edge.

Output

Print the sum of the weights of the Minimum Spanning Tree.

Constraints

1 ≤ |V| ≤ 10,000

0 ≤ |E| ≤ 100,000

0 ≤ wi ≤ 10,000

The graph is connected

There are no parallel edges

There are no self-loops

Sample Input 1

4 6
0 1 2
1 2 1
2 3 1
3 0 1
0 2 3
1 3 5

Sample Output 1

3

Sample Input 2

6 9
0 1 1
0 2 3
1 2 1
1 3 7
2 4 1
1 4 3
3 4 1
3 5 1
4 5 6

Sample Output 2

5

Solution in Rust (judge verdict: Accepted)

#[derive(Debug, Clone)]
struct UnionFind {
    table: Vec<i32>,
    num: usize,
}
impl UnionFind {
    fn new(n: usize) -> UnionFind {
        UnionFind {
            table: vec![-1; n],
            num: n,
        }
    }
    fn root(&mut self, x: usize) -> usize {
        let mut r = x;
        if self.table[x] >= 0 {
            let t = self.table[x] as usize;
            r = self.root(t);
            self.table[x] = r as i32;
        }
        r
    }
    fn find(&mut self, x: usize, y: usize) -> bool {
        self.root(x) == self.root(y)
    }
    fn size(&mut self, x: usize) -> usize {
        let r = self.root(x);
        (-self.table[r]) as usize
    }
    fn union(&mut self, x: usize, y: usize) {
        let xr = self.root(x);
        let yr = self.root(y);
        if xr != yr {
            if self.size(xr) < self.size(yr) {
                self.table[yr] += self.table[xr];
                self.table[xr] = yr as i32;
            } else {
                self.table[xr] += self.table[yr];
                self.table[yr] = xr as i32;
            }
            self.num -= 1;
        }
    }
}

#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Ord, Eq)]
struct Edge {
    from: usize,
    to: usize,
    cost: i64,
}

// O(V^3)
fn mst_cost(mut edges: Vec<Edge>, n: usize) -> i64 {
    let mut res = 0;
    let mut uf = UnionFind::new(n);
    edges.sort_by(|x, y| x.cost.cmp(&y.cost));
    for e in edges {
        if !uf.find(e.from, e.to) {
            res += e.cost;
            uf.union(e.from, e.to);
        }
        if uf.num == 1 {
            break;
        }
    }
    res
}

fn solve() {
    let (v, e): (usize, usize) = (read::<usize>(), read::<usize>());
    let mut edges = vec![];
    for _ in 0..e {
        let edge = Edge {
            from: read(),
            to: read(),
            cost: read(),
        };
        edges.push(edge);
    }
    println!("{}", mst_cost(edges, v));
}

fn main() {
    let stack_size = 104_857_600;
    let thd = std::thread::Builder::new().stack_size(stack_size);
    thd.spawn(|| solve()).unwrap().join().unwrap();
}

// =========
#[allow(unused_imports)]
use std::cmp::{max, min, Ord, Ordering, PartialOrd};
#[allow(unused_imports)]
use std::collections::{BinaryHeap, HashMap, HashSet};
#[allow(unused_imports)]
use std::process::exit;

#[allow(dead_code)]
const MOD: usize = 1000000007;
const INF: usize = 100_000_000_000;

fn read<T: std::str::FromStr>() -> T {
    use std::io::Read;
    let stdin = std::io::stdin();
    let stdin = stdin.lock();
    let token: String = stdin
        .bytes()
        .map(|c| c.expect("failed to read char") as char)
        .skip_while(|c| c.is_whitespace())
        .take_while(|c| !c.is_whitespace())
        .collect();
    token.parse().ok().expect("failed to parse token")
}

// =========