Submission #43979237


Source Code Expand

use dsu::*;
use proconio::input;

fn main() {
    input! {
        n: usize,
        q: usize,
        pab: [(usize, usize, usize); q],
    };
    let mut dsu = Dsu::new(n);
    for (p, a, b) in pab {
        match p {
            0 => {
                dsu.merge(a, b);
            }
            1 => {
                let ans = dsu.same(a, b);
                println!("{}", if ans { "Yes" } else { "No" });
            }
            _ => unreachable!(),
        }
    }
}

//https://github.com/rust-lang-ja/ac-library-rs

pub mod dsu {
    /// Implement (union by size) + (path compression)
    /// Reference:
    /// Zvi Galil and Giuseppe F. Italiano,
    /// Data structures and algorithms for disjoint set union problems
    pub struct Dsu {
        n: usize,
        // root node: -1 * component size
        // otherwise: parent
        parent_or_size: Vec<i32>,
    }

    impl Dsu {
        // 0 <= size <= 10^8 is constrained.
        pub fn new(size: usize) -> Self {
            Self {
                n: size,
                parent_or_size: vec![-1; size],
            }
        }
        pub fn merge(&mut self, a: usize, b: usize) -> usize {
            assert!(a < self.n);
            assert!(b < self.n);
            let (mut x, mut y) = (self.leader(a), self.leader(b));
            if x == y {
                return x;
            }
            if -self.parent_or_size[x] < -self.parent_or_size[y] {
                std::mem::swap(&mut x, &mut y);
            }
            self.parent_or_size[x] += self.parent_or_size[y];
            self.parent_or_size[y] = x as i32;
            x
        }

        pub fn same(&mut self, a: usize, b: usize) -> bool {
            assert!(a < self.n);
            assert!(b < self.n);
            self.leader(a) == self.leader(b)
        }
        pub fn leader(&mut self, a: usize) -> usize {
            assert!(a < self.n);
            if self.parent_or_size[a] < 0 {
                return a;
            }
            self.parent_or_size[a] = self.leader(self.parent_or_size[a] as usize) as i32;
            self.parent_or_size[a] as usize
        }
        pub fn size(&mut self, a: usize) -> usize {
            assert!(a < self.n);
            let x = self.leader(a);
            -self.parent_or_size[x] as usize
        }
        pub fn groups(&mut self) -> Vec<Vec<usize>> {
            let mut leader_buf = vec![0; self.n];
            let mut group_size = vec![0; self.n];
            for i in 0..self.n {
                leader_buf[i] = self.leader(i);
                group_size[leader_buf[i]] += 1;
            }
            let mut result = vec![Vec::new(); self.n];
            for i in 0..self.n {
                result[i].reserve(group_size[i]);
            }
            for i in 0..self.n {
                result[leader_buf[i]].push(i);
            }
            result
                .into_iter()
                .filter(|x| !x.is_empty())
                .collect::<Vec<Vec<usize>>>()
        }
    }

    #[cfg(test)]
    mod tests {
        use super::*;

        #[test]
        fn dsu_works() {
            let mut d = Dsu::new(4);
            d.merge(0, 1);
            assert_eq!(d.same(0, 1), true);
            d.merge(1, 2);
            assert_eq!(d.same(0, 2), true);
            assert_eq!(d.size(0), 3);
            assert_eq!(d.same(0, 3), false);
            assert_eq!(d.groups(), vec![vec![0, 1, 2], vec![3]]);
        }
    }
}

Submission Info

Submission Time
Task B - Union Find
User bouzuya
Language Rust (1.42.0)
Score 100
Code Size 3433 Byte
Status AC
Exec Time 320 ms
Memory 9884 KiB

Judge Result

Set Name Sample All
Score / Max Score 0 / 0 100 / 100
Status
AC × 1
AC × 19
Set Name Test Cases
Sample 00_sample_01.txt
All 00_sample_01.txt, subtask_01_01.txt, subtask_01_02.txt, subtask_01_03.txt, subtask_01_04.txt, subtask_01_05.txt, subtask_01_06.txt, subtask_01_07.txt, subtask_01_08.txt, subtask_01_09.txt, subtask_01_10.txt, subtask_01_11.txt, subtask_01_12.txt, subtask_01_13.txt, subtask_01_14.txt, subtask_01_15.txt, subtask_01_16.txt, subtask_01_17.txt, subtask_01_18.txt
Case Name Status Exec Time Memory
00_sample_01.txt AC 7 ms 2092 KiB
subtask_01_01.txt AC 195 ms 6148 KiB
subtask_01_02.txt AC 6 ms 2256 KiB
subtask_01_03.txt AC 319 ms 7740 KiB
subtask_01_04.txt AC 316 ms 9852 KiB
subtask_01_05.txt AC 31 ms 2328 KiB
subtask_01_06.txt AC 26 ms 2752 KiB
subtask_01_07.txt AC 312 ms 8380 KiB
subtask_01_08.txt AC 320 ms 9820 KiB
subtask_01_09.txt AC 6 ms 2164 KiB
subtask_01_10.txt AC 2 ms 2252 KiB
subtask_01_11.txt AC 310 ms 7744 KiB
subtask_01_12.txt AC 313 ms 9852 KiB
subtask_01_13.txt AC 251 ms 7556 KiB
subtask_01_14.txt AC 10 ms 2220 KiB
subtask_01_15.txt AC 306 ms 8116 KiB
subtask_01_16.txt AC 312 ms 9884 KiB
subtask_01_17.txt AC 174 ms 9816 KiB
subtask_01_18.txt AC 182 ms 9760 KiB