https://atcoder.jp/contests/abc302/tasks/abc302_e
Queryをenumにして、matchで分けるときれいに書けますね。
HashMapでborrowするとややこしいことになりますね。
// Isolation #![allow(non_snake_case)] use std::collections::{HashMap, HashSet}; //////////////////// library //////////////////// fn read<T: std::str::FromStr>() -> T { let mut line = String::new(); std::io::stdin().read_line(&mut line).ok(); line.trim().parse().ok().unwrap() } fn read_vec<T: std::str::FromStr>() -> Vec<T> { read::<String>().split_whitespace() .map(|e| e.parse().ok().unwrap()).collect() } //////////////////// process //////////////////// fn read_input() -> (usize, usize) { let v = read_vec(); let N = v[0]; let Q = v[1]; (N, Q) } type Node = usize; type Graph = HashMap<Node, HashSet<Node>>; enum Query { Add(usize, Node, Node), Remove(usize, Node) } fn read_query() -> Query { let v = read_vec(); if v[0] == 1 { Query::Add(v[0], v[1], v[2]) } else { Query::Remove(v[0], v[1]) } } fn add_edge(v: Node, w: Node, graph: &mut Graph) -> usize { let e1 = graph.entry(v).or_insert(HashSet::new()); e1.insert(w); let num1 = if e1.len() == 1 { 1 } else { 0 }; let e2 = graph.entry(w).or_insert(HashSet::new()); e2.insert(v); let num2 = if e2.len() == 1 { 1 } else { 0 }; num1 + num2 } fn remove_node(v: Node, graph: &mut Graph) -> usize { let op = graph.get(&v); if op.is_none() { return 0 } let s = op.unwrap(); if s.is_empty() { return 0 } let num = s.iter().filter(|w| graph.get(w).unwrap().len() == 1).count(); let neighbors: Vec<Node> = s.iter().map(|&w| w).collect(); for w in neighbors.iter() { graph.get_mut(w).unwrap().remove(&v); } let s1 = graph.get_mut(&v).unwrap(); s1.clear(); num + 1 } fn f(N: usize, Q: usize) { let mut graph: Graph = Graph::new(); let mut num_isolated = N; for _ in 0..Q { match read_query() { Query::Add(_, v, w) => { num_isolated -= add_edge(v, w, &mut graph) }, Query::Remove(_, v) => { num_isolated += remove_node(v, &mut graph) } } println!("{}", num_isolated) } } //////////////////// main //////////////////// fn main() { let (N, Q) = read_input(); f(N, Q) }