Module c
Expand description
§ABC 399 C - Make it Forest
refs: https://atcoder.jp/contests/abc399/tasks/abc399_c
与えられたグラフが森となる = 各連結成分の辺の数が, ちょうど頂点の数 - 1 となる, と読み替えて良い.
連結している頂点がどこかだけ識別できれば良いため, Union Find でさくっと対応が効く.
use std::{cmp::Ordering, collections::HashMap};
use proconio::input;
struct UnionFind {
parent: Vec<usize>,
rank: Vec<usize>,
}
impl UnionFind {
fn new(n: usize) -> Self {
UnionFind {
parent: (0..n).collect(),
rank: vec![1; n],
}
}
fn find(&mut self, x: usize) -> usize {
if self.parent[x] != x {
self.parent[x] = self.find(self.parent[x]);
}
self.parent[x]
}
fn union(&mut self, x: usize, y: usize) {
let root_x = self.find(x);
let root_y = self.find(y);
if root_x == root_y {
return;
}
match self.rank[root_x].cmp(&self.rank[root_y]) {
Ordering::Less => {
self.parent[root_x] = root_y;
}
Ordering::Greater => {
self.parent[root_y] = root_x;
}
_ => {
self.parent[root_y] = root_x;
self.rank[root_x] += 1;
}
}
}
}
fn main() {
input! {
n: usize, m: usize,
edges: [(usize, usize); m],
}
let mut uf = UnionFind::new(n);
for (a, b) in edges {
uf.union(a - 1, b - 1);
}
let group_count = (0..n)
.map(|i| uf.find(i))
.fold(HashMap::new(), |mut acc, x| {
*acc.entry(x).or_insert(0) += 1;
acc
});
let available_edge_count = group_count.values().map(|&x| x - 1).sum::<usize>();
println!("{}", m - available_edge_count);
}