結果
問題 | No.1473 おでぶなおばけさん |
ユーザー | RheoTommy |
提出日時 | 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 |
ソースコード
#![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(); } } }