結果

問題 No.1473 おでぶなおばけさん
ユーザー RheoTommyRheoTommy
提出日時 2021-04-09 22:03:59
言語 Rust
(1.77.0 + proconio)
結果
AC  
実行時間 244 ms / 2,000 ms
コード長 10,045 bytes
コンパイル時間 12,054 ms
コンパイル使用メモリ 404,672 KB
実行使用メモリ 19,216 KB
最終ジャッジ日時 2024-06-25 05:31:45
合計ジャッジ時間 17,927 ms
ジャッジサーバーID
(参考情報)
judge3 / judge2
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 1 ms
5,248 KB
testcase_01 AC 1 ms
5,248 KB
testcase_02 AC 222 ms
18,048 KB
testcase_03 AC 155 ms
15,616 KB
testcase_04 AC 112 ms
11,008 KB
testcase_05 AC 31 ms
5,376 KB
testcase_06 AC 166 ms
16,156 KB
testcase_07 AC 244 ms
19,096 KB
testcase_08 AC 244 ms
19,216 KB
testcase_09 AC 244 ms
19,088 KB
testcase_10 AC 22 ms
10,240 KB
testcase_11 AC 24 ms
11,648 KB
testcase_12 AC 24 ms
11,008 KB
testcase_13 AC 16 ms
7,680 KB
testcase_14 AC 11 ms
5,888 KB
testcase_15 AC 21 ms
10,112 KB
testcase_16 AC 21 ms
9,344 KB
testcase_17 AC 2 ms
5,376 KB
testcase_18 AC 4 ms
5,376 KB
testcase_19 AC 36 ms
9,344 KB
testcase_20 AC 93 ms
13,696 KB
testcase_21 AC 69 ms
12,288 KB
testcase_22 AC 66 ms
14,976 KB
testcase_23 AC 58 ms
13,872 KB
testcase_24 AC 56 ms
12,896 KB
testcase_25 AC 65 ms
15,232 KB
testcase_26 AC 63 ms
15,508 KB
testcase_27 AC 17 ms
6,656 KB
testcase_28 AC 166 ms
18,816 KB
testcase_29 AC 88 ms
12,740 KB
testcase_30 AC 127 ms
14,388 KB
testcase_31 AC 167 ms
18,176 KB
testcase_32 AC 115 ms
16,296 KB
testcase_33 AC 99 ms
13,312 KB
testcase_34 AC 50 ms
7,912 KB
testcase_35 AC 39 ms
8,064 KB
testcase_36 AC 76 ms
10,752 KB
testcase_37 AC 115 ms
13,696 KB
testcase_38 AC 16 ms
5,376 KB
testcase_39 AC 22 ms
9,728 KB
testcase_40 AC 22 ms
9,600 KB
testcase_41 AC 19 ms
8,872 KB
testcase_42 AC 20 ms
8,812 KB
testcase_43 AC 81 ms
13,824 KB
testcase_44 AC 81 ms
13,824 KB
testcase_45 AC 80 ms
13,824 KB
testcase_46 AC 163 ms
12,708 KB
testcase_47 AC 207 ms
15,104 KB
testcase_48 AC 184 ms
14,288 KB
権限があれば一括ダウンロードができます

ソースコード

diff #

#![allow(unused_macros)]
#![allow(dead_code)]
#![allow(unused_imports)]

// # ファイル構成
// - use 宣言
// - lib モジュール
// - main 関数
// - basic モジュール
//
// 常に使うテンプレートライブラリは basic モジュール内にあります。
// 問題に応じて使うライブラリ lib モジュール内にコピペしています。
// ライブラリのコードはこちら → https://github.com/RheoTommy/at_coder
// Twitter はこちら → https://twitter.com/RheoTommy

use std::collections::*;
use std::io::{stdout, BufWriter, Write};

use crate::basic::*;
use crate::lib::*;

pub mod lib {
    /// UnionFind構造体
    /// UnionFind構造体
    pub struct UnionFindTree {
        /// 頂点`i`の親を格納する配列
        parents: Vec<usize>,
        /// 頂点`i`が親であるときのその木の頂点数
        sizes: Vec<usize>,
        /// 重み付きUnionFindを使う際の重みの格納配列
        weights: Vec<i64>,
        /// 頂点`i`が属する木がループを持っているかどうか
        has_loops: Vec<bool>,
        /// 連結成分数
        number_of_tree: usize,
    }

    impl UnionFindTree {
        /// UnionFind初期化
        /// 計算量はO(n)
        pub fn new(n: usize) -> Self {
            let parents = (0..n).collect();
            let sizes = vec![1; n];
            let weights = vec![0; n];
            let has_loops = vec![false; n];
            UnionFindTree {
                parents,
                sizes,
                weights,
                has_loops,
                number_of_tree: n,
            }
        }
        /// 親を再帰的に求め、途中の計算結果をもとに親の書き換えを行う関数
        /// 計算量はO(a(n)))
        pub fn root(&mut self, x: usize) -> usize {
            if self.parents[x] == x {
                x
            } else {
                let tmp = self.root(self.parents[x]);
                self.weights[x] += self.weights[self.parents[x]];
                self.parents[x] = tmp;
                tmp
            }
        }
        pub fn size(&mut self, x: usize) -> usize {
            let y = self.root(x);
            self.sizes[y]
        }
        pub fn has_loop(&mut self, x: usize) -> bool {
            let y = self.root(x);
            self.has_loops[y]
        }
        /// 2つの頂点が同じ木に属しているかの判定
        /// `self.root()`を呼び出すため、`&mut self`を引数に取る。そのため、命名に`is_`を使っていない
        /// 計算量はO(a(n))
        pub fn same(&mut self, x: usize, y: usize) -> bool {
            self.root(x) == self.root(y)
        }
        /// 重み付きUnionFindを考える際のUnite関数
        /// 計算量はO(a(n))
        pub fn unite_with_weight(&mut self, x: usize, y: usize, w: i64) {
            let root_x = self.root(x);
            let root_y = self.root(y);
            if self.same(x, y) {
                self.has_loops[root_x] = true;
                self.has_loops[root_y] = true;
            } else if self.sizes[root_x] >= self.sizes[root_y] {
                self.number_of_tree -= 1;
                self.parents[root_y] = root_x;
                self.has_loops[root_x] |= self.has_loops[root_y];
                self.sizes[root_x] += self.sizes[root_y];
                self.weights[root_y] = -w - self.weights[y] + self.weights[x];
            } else {
                self.number_of_tree -= 1;
                self.parents[root_x] = root_y;
                self.has_loops[root_y] |= self.has_loops[root_x];
                self.sizes[root_y] += self.sizes[root_x];
                self.weights[root_x] = w + self.weights[y] - self.weights[x];
            }
        }
        /// 重みを考慮しない際のUnite関数
        /// 重みとして0を与えているだけであり、計算量は同じくO(a(n))
        pub fn unite(&mut self, x: usize, y: usize) {
            self.unite_with_weight(x, y, 0);
        }
        /// 重み付きUnionFindにおいて、2つの頂点の距離を返す関数
        /// 2つの頂点が同じ木に属していない場合は`None`を返す
        pub fn diff(&mut self, x: usize, y: usize) -> Option<i64> {
            if self.same(x, y) {
                Some(self.weights[x] - self.weights[y])
            } else {
                None
            }
        }
        pub fn is_parent(&self, x: usize) -> bool {
            self.parents[x] == x
        }
        pub fn number_of_tree(&self) -> usize {
            self.number_of_tree
        }
    }

    /// 関数Fを適用すると[false..false,true..true]の形にできるような配列において、初めてtrueになるIndexを返す
    /// O(log n)
    pub trait BinarySearch<T> {
        /// 存在しなかった場合は配列の長さを返す
        fn lower_bound(&self, f: impl FnMut(&T) -> bool) -> usize;
        /// 存在しなかった場合はNoneを返す
        fn lower_bound_safe(&self, f: impl FnMut(&T) -> bool) -> Option<usize>;
    }

    impl<T> BinarySearch<T> for [T] {
        /// 任意のランダムアクセス可能なスライスに対して実行可能な実装
        fn lower_bound(&self, mut f: impl FnMut(&T) -> bool) -> usize {
            let mut left: isize = -1;
            let mut right = self.len() as isize;
            while right - left > 1 {
                let mid = (left + right) / 2;
                if f(&self[mid as usize]) {
                    right = mid;
                } else {
                    left = mid;
                }
            }
            right as usize
        }
        fn lower_bound_safe(&self, f: impl FnMut(&T) -> bool) -> Option<usize> {
            let i = self.lower_bound(f);
            if i == self.len() {
                None
            } else {
                Some(i)
            }
        }
    }

    pub fn lower_bound<
        T: Copy + std::ops::Add<Output = T> + std::ops::Div<Output = T> + From<i32>,
    >(
        mut l: T,
        mut r: T,
        mut f: impl FnMut(T) -> bool,
        mut g: impl FnMut(T, T) -> bool,
    ) -> Option<T> {
        if !f(r) {
            return None;
        }
        while g(l, r) {
            let mid = (l + r) / T::from(2i32);
            if f(mid) {
                r = mid;
            } else {
                l = mid;
            }
        }
        Some(r)
    }
}

fn main() {
    let mut io = IO::new();
    let n = io.next_usize();
    let m = io.next_usize();
    let mut vertexes = vec![vec![]; n];
    let mut edges = vec![];
    for _ in 0..m {
        let s = io.next_usize() - 1;
        let t = io.next_usize() - 1;
        let d = io.next_int();
        edges.push((s, t, d));
        vertexes[s].push((t, d));
        vertexes[t].push((s, d));
    }

    let judge = |w: i64| {
        let mut uf = UnionFindTree::new(n);
        for &(s, t, d) in &edges {
            if w <= d {
                uf.unite(s, t);
            }
        }
        uf.same(0, n - 1)
    };

    let max = lower_bound(2 * 1000000000, 0i64, judge, |a, b| (a - b).abs() > 1).unwrap();
    io.print(max);

    let mut dp = vec![U_INF; n];
    dp[0] = 0;
    let mut queue = VecDeque::new();
    queue.push_back(0);
    while let Some(now) = queue.pop_front() {
        for &(t, d) in &vertexes[now] {
            if d >= max && dp[t] > dp[now] + 1 {
                dp[t] = dp[now] + 1;
                queue.push_back(t);
            }
        }
    }
    io.print(" ");
    io.println(dp[n - 1]);
}

pub mod basic {
    pub const U_INF: u64 = (1 << 60) + (1 << 30);
    pub const I_INF: i64 = (1 << 60) + (1 << 30);

    pub struct IO {
        iter: std::str::SplitAsciiWhitespace<'static>,
        buf: std::io::BufWriter<std::io::StdoutLock<'static>>,
    }

    impl IO {
        pub fn new() -> Self {
            use std::io::*;
            let mut input = String::new();
            std::io::stdin().read_to_string(&mut input).unwrap();
            let input = Box::leak(input.into_boxed_str());
            let out = Box::new(stdout());
            IO {
                iter: input.split_ascii_whitespace(),
                buf: BufWriter::new(Box::leak(out).lock()),
            }
        }

        pub fn next_str(&mut self) -> &str {
            self.iter.next().unwrap()
        }

        pub fn next<T: std::str::FromStr>(&mut self) -> T
        where
            <T as std::str::FromStr>::Err: std::fmt::Debug,
        {
            self.iter.next().unwrap().parse().unwrap()
        }

        pub fn next_usize(&mut self) -> usize {
            self.next()
        }

        pub fn next_uint(&mut self) -> u64 {
            self.next()
        }

        pub fn next_int(&mut self) -> i64 {
            self.next()
        }

        pub fn next_float(&mut self) -> f64 {
            self.next()
        }

        pub fn next_chars(&mut self) -> std::str::Chars {
            self.next_str().chars()
        }

        pub fn next_vec<T: std::str::FromStr>(&mut self, n: usize) -> Vec<T>
        where
            <T as std::str::FromStr>::Err: std::fmt::Debug,
        {
            (0..n).map(|_| self.next()).collect::<Vec<_>>()
        }

        pub fn print<T: std::fmt::Display>(&mut self, t: T) {
            use std::io::Write;
            write!(self.buf, "{}", t).unwrap();
        }

        pub fn println<T: std::fmt::Display>(&mut self, t: T) {
            self.print(t);
            self.print("\n");
        }

        pub fn print_iter<T: std::fmt::Display, I: Iterator<Item = T>>(
            &mut self,
            mut iter: I,
            sep: &str,
        ) {
            if let Some(v) = iter.next() {
                self.print(v);
                for vi in iter {
                    self.print(sep);
                    self.print(vi);
                }
            }
            self.print("\n");
        }

        pub fn flush(&mut self) {
            use std::io::Write;
            self.buf.flush().unwrap();
        }
    }
}
0