結果

問題 No.1390 Get together
ユーザー tzyvrntzyvrn
提出日時 2021-02-12 23:32:00
言語 Rust
(1.77.0)
結果
AC  
実行時間 56 ms / 2,000 ms
コード長 4,376 bytes
コンパイル時間 2,572 ms
コンパイル使用メモリ 162,288 KB
実行使用メモリ 10,484 KB
最終ジャッジ日時 2023-09-27 07:06:22
合計ジャッジ時間 5,082 ms
ジャッジサーバーID
(参考情報)
judge15 / judge13
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 1 ms
4,376 KB
testcase_01 AC 0 ms
4,376 KB
testcase_02 AC 0 ms
4,380 KB
testcase_03 AC 2 ms
4,376 KB
testcase_04 AC 1 ms
4,376 KB
testcase_05 AC 1 ms
4,380 KB
testcase_06 AC 1 ms
4,376 KB
testcase_07 AC 2 ms
4,380 KB
testcase_08 AC 2 ms
4,376 KB
testcase_09 AC 2 ms
4,376 KB
testcase_10 AC 1 ms
4,376 KB
testcase_11 AC 1 ms
4,380 KB
testcase_12 AC 1 ms
4,376 KB
testcase_13 AC 1 ms
4,376 KB
testcase_14 AC 1 ms
4,376 KB
testcase_15 AC 1 ms
4,380 KB
testcase_16 AC 43 ms
5,992 KB
testcase_17 AC 49 ms
10,448 KB
testcase_18 AC 36 ms
5,908 KB
testcase_19 AC 56 ms
10,448 KB
testcase_20 AC 54 ms
10,340 KB
testcase_21 AC 53 ms
10,440 KB
testcase_22 AC 50 ms
8,952 KB
testcase_23 AC 50 ms
9,032 KB
testcase_24 AC 48 ms
8,904 KB
testcase_25 AC 53 ms
10,408 KB
testcase_26 AC 53 ms
10,484 KB
testcase_27 AC 53 ms
10,432 KB
testcase_28 AC 53 ms
10,440 KB
testcase_29 AC 53 ms
10,380 KB
testcase_30 AC 53 ms
10,408 KB
testcase_31 AC 53 ms
10,484 KB
権限があれば一括ダウンロードができます

ソースコード

diff #

#[allow(unused_macros)]
macro_rules! getl {
    ( $( $t:ty ),* ) => {
        {
            let mut s = String::new();
            std::io::stdin().read_line(&mut s).unwrap();
            let s = s.trim_end();
            let mut ws = s.split_whitespace();
            ($(ws.next().unwrap().parse::<$t>().unwrap()),*)
        }
    };
}

#[allow(unused_macros)]
macro_rules! getl_vec {
    ( $t:ty ) => {{
        let mut s = String::new();
        std::io::stdin().read_line(&mut s).unwrap();
        let s = s.trim_end();
        s.split_whitespace()
            .map(|x| x.parse().unwrap())
            .collect::<Vec<$t>>()
    }};
}

fn main() {
    let (n, m) = getl!(usize, usize);
    let mut slimes = vec![];
    for _ in 0..n {
        let (b, c) = getl!(usize, usize);
        slimes.push((b - 1, c - 1));
    }

    let mut color_leaders = vec![None; n];
    let mut dsu = Dsu::new(m);
    for (b, c) in slimes {
        match color_leaders[c] {
            Some(b2) => {
                dsu.merge(b, b2);
            }
            None => color_leaders[c] = Some(b),
        }
    }

    let mut seen = HashSet::new();
    let mut ans = 0;
    for i in 0..m {
        if seen.contains(&dsu.leader(i)) {
            continue;
        } else {
            ans += dsu.size(i) - 1;
            seen.insert(dsu.leader(i));
        }
    }
    println!("{}", ans);
}

//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]]);
        }
    }
}
use std::collections::HashSet;

use dsu::*;
0