// https://infoarena.ro/problema/dfs
use std::{
collections::*, fmt::*, fs::{write, *}, mem::*, str::*
};
fn split_in_x_var<T: FromStr>(string: &str) -> Vec<T> where T::Err: Debug {
string.split_whitespace().map(|x| x.parse::<T>().unwrap()).collect::<Vec<T>>()
}
fn split_in_x<const N: usize, T: FromStr + Debug>(string: &str) -> [T; N] where T::Err: Debug {
string.split_whitespace().map(|x| x.parse::<T>().unwrap()).collect::<Vec<T>>().try_into().unwrap()
}
fn dfs(nod: usize, verificate: &mut HashSet<usize>, nodurile: &Vec<HashSet<usize>>) {
verificate.insert(nod);
for noduri_afara in &nodurile[nod] {
if !verificate.contains(&*noduri_afara) {
dfs(*noduri_afara, verificate, nodurile);
}
}
}
fn main() {
let content = read_to_string("dfs.in").unwrap();
let mut lines = content.lines();
let [noduri, _muchii]: [usize; 2] = split_in_x(lines.next().unwrap());
let mut nodurile = vec![HashSet::new(); noduri];
for line in lines {
let [muchie1, muchie2]: [usize; 2] = split_in_x(line);
nodurile[muchie1 - 1].insert(muchie2 - 1);
nodurile[muchie2 - 1].insert(muchie1 - 1);
}
let mut nr_componente_conexe = 0;
let mut noduri_verificate = HashSet::new();
for nod in 0..nodurile.len() {
if !noduri_verificate.contains(&nod) {
nr_componente_conexe += 1;
dfs(nod, &mut noduri_verificate, &nodurile);
}
}
write("dfs.out", nr_componente_conexe.to_string()).unwrap();
}