Submission #62131403


Source Code Expand

// https://atcoder.jp/contests/arc191/tasks/arc191_d
use crate::algo_lib::collections::default_map::DefaultHashMap;
use crate::algo_lib::collections::min_max::MinimMaxim;
use crate::algo_lib::collections::vec_ext::inc_dec::IncDec;
use crate::algo_lib::graph::edge_distances::EdgeAlgos;
use crate::algo_lib::graph::Graph;
use crate::algo_lib::io::input::Input;
use crate::algo_lib::io::output::Output;
use crate::algo_lib::misc::test_type::TaskType;
use crate::algo_lib::misc::test_type::TestType;
type PreCalc = ();
fn solve(input: &mut Input, out: &mut Output, _test_case: usize, _data: &mut PreCalc) {
    let n = input.read_size();
    let m = input.read_size();
    let s = input.read_size() - 1;
    let t = input.read_size() - 1;
    let edges = input.read_size_pair_vec(m).dec();
    let graph = Graph::with_biedges(n, &edges);
    let ds = graph.edge_distances(s);
    let dt = graph.edge_distances(t);
    let direct = ds[t];
    let mut by_d = DefaultHashMap::new(Vec::new());
    for i in 0..n {
        by_d[(ds[i], dt[i])].push(i);
    }
    let mut ans = None;
    for ((ds, dt), verts) in by_d {
        if verts.len() > 1 {
            ans.minim(2 * (ds + dt));
        }
        if ds + dt != direct && ds.abs_diff(dt) != direct {
            ans.minim(direct + ds + dt);
        }
    }
    out.print_line(ans);
}
pub static TEST_TYPE: TestType = TestType::Single;
pub static TASK_TYPE: TaskType = TaskType::Classic;
pub(crate) fn run(mut input: Input, mut output: Output) -> bool {
    let mut pre_calc = ();
    match TEST_TYPE {
        TestType::Single => solve(&mut input, &mut output, 1, &mut pre_calc),
        TestType::MultiNumber => {
            let t = input.read();
            for i in 1..=t {
                solve(&mut input, &mut output, i, &mut pre_calc);
            }
        }
        TestType::MultiEof => {
            let mut i = 1;
            while input.peek().is_some() {
                solve(&mut input, &mut output, i, &mut pre_calc);
                i += 1;
            }
        }
    }
    output.flush();
    match TASK_TYPE {
        TaskType::Classic => input.is_empty(),
        TaskType::Interactive => true,
    }
}


fn main() {
    let input = crate::algo_lib::io::input::Input::stdin();
    let output = crate::algo_lib::io::output::Output::stdout();
    run(input, output);
}
pub mod algo_lib {
pub mod collections {
pub mod default_map {
use crate::algo_lib::collections::fx_hash_map::FxHashMap;
use std::collections::BTreeMap;
use std::fmt::Debug;
use std::hash::Hash;
use std::ops::{Deref, DerefMut, Index, IndexMut};
macro_rules! default_map {
    (
        $name:ident, $inner:ident, $key_trait:path, $into_values:ident, $into_iter:ident
    ) => {
        #[derive(Clone, Eq, PartialEq, Debug, Default)] pub struct $name < K : Eq +
        $key_trait, V > { inner : $inner < K, V >, default : V, } impl < K : Eq +
        $key_trait, V > Deref for $name < K, V > { type Target = $inner < K, V >; fn
        deref(& self) -> & Self::Target { & self.inner } } impl < K : Eq + $key_trait, V
        > DerefMut for $name < K, V > { fn deref_mut(& mut self) -> & mut Self::Target {
        & mut self.inner } } impl < K : Eq + $key_trait, V : Clone > $name < K, V > { pub
        fn new(default : V) -> Self { Self { inner : $inner ::default(), default, } } pub
        fn get(& self, key : & K) -> & V { self.inner.get(key).unwrap_or(& self.default)
        } pub fn get_mut(& mut self, key : K) -> & mut V { self.inner.entry(key)
        .or_insert_with(|| self.default.clone()) } pub fn into_values(self) ->
        $into_values < K, V > { self.inner.into_values() } } impl < K : Eq + $key_trait,
        V : Clone > Index < K > for $name < K, V > { type Output = V; fn index(& self,
        index : K) -> & Self::Output { self.get(& index) } } impl < K : Eq + $key_trait,
        V : Clone > IndexMut < K > for $name < K, V > { fn index_mut(& mut self, index :
        K) -> & mut Self::Output { self.get_mut(index) } } impl < K : Eq + $key_trait, V
        > IntoIterator for $name < K, V > { type Item = (K, V); type IntoIter =
        $into_iter < K, V >; fn into_iter(self) -> Self::IntoIter { self.inner
        .into_iter() } } impl < K : Eq + $key_trait, V : Default > FromIterator < (K, V)
        > for $name < K, V > { fn from_iter < T : IntoIterator < Item = (K, V) >> (iter :
        T) -> Self { Self { inner : $inner ::from_iter(iter), default : V::default(), } }
        }
    };
}
type HashMapIntoValues<K, V> = std::collections::hash_map::IntoValues<K, V>;
type HashMapIntoIter<K, V> = std::collections::hash_map::IntoIter<K, V>;
default_map!(DefaultHashMap, FxHashMap, Hash, HashMapIntoValues, HashMapIntoIter);
type TreeMapIntoValues<K, V> = std::collections::btree_map::IntoValues<K, V>;
type TreeMapIntoIter<K, V> = std::collections::btree_map::IntoIter<K, V>;
default_map!(DefaultTreeMap, BTreeMap, Ord, TreeMapIntoValues, TreeMapIntoIter);
pub fn qty<T: Eq + Hash + Clone>(arr: &[T]) -> DefaultHashMap<T, usize> {
    let mut map = DefaultHashMap::new(0);
    for item in arr {
        map[item.clone()] += 1;
    }
    map
}
pub fn by_index<T: Eq + Hash + Clone>(arr: &[T]) -> DefaultHashMap<T, Vec<usize>> {
    let mut map = DefaultHashMap::new(Vec::new());
    for (i, item) in arr.iter().enumerate() {
        map[item.clone()].push(i);
    }
    map
}
}
pub mod dsu {
use crate::algo_lib::collections::slice_ext::bounds::Bounds;
use crate::algo_lib::collections::slice_ext::indices::Indices;
use std::cell::Cell;
#[derive(Clone)]
pub struct DSU {
    id: Vec<Cell<i32>>,
    count: usize,
}
impl DSU {
    pub fn new(n: usize) -> Self {
        Self {
            id: vec![Cell::new(- 1); n],
            count: n,
        }
    }
    pub fn size(&self, i: usize) -> usize {
        (-self.id[self.find(i)].get()) as usize
    }
    #[allow(clippy::len_without_is_empty)]
    pub fn len(&self) -> usize {
        self.id.len()
    }
    pub fn iter(&self) -> impl Iterator<Item = usize> + '_ {
        self.id
            .iter()
            .enumerate()
            .filter_map(|(i, id)| if id.get() < 0 { Some(i) } else { None })
    }
    pub fn set_count(&self) -> usize {
        self.count
    }
    pub fn union(&mut self, mut a: usize, mut b: usize) -> bool {
        a = self.find(a);
        b = self.find(b);
        if a == b {
            false
        } else {
            self.id[a].set(self.id[a].get() + self.id[b].get());
            self.id[b].set(a as i32);
            self.count -= 1;
            true
        }
    }
    pub fn find(&self, i: usize) -> usize {
        if self.id[i].get() >= 0 {
            let res = self.find(self.id[i].get() as usize);
            self.id[i].set(res as i32);
            res
        } else {
            i
        }
    }
    pub fn clear(&mut self) {
        self.count = self.id.len();
        self.id.fill(Cell::new(-1));
    }
    pub fn parts(&self) -> Vec<Vec<usize>> {
        let roots: Vec<_> = self.iter().collect();
        let mut res = vec![Vec::new(); roots.len()];
        for i in self.id.indices() {
            res[roots.as_slice().bin_search(&self.find(i)).unwrap()].push(i);
        }
        res
    }
}
}
pub mod fx_hash_map {
use crate::algo_lib::misc::lazy_lock::LazyLock;
use std::convert::TryInto;
use std::time::SystemTime;
use std::{
    collections::{HashMap, HashSet},
    hash::{BuildHasherDefault, Hasher},
    ops::BitXor,
};
pub type FxHashMap<K, V> = HashMap<K, V, BuildHasherDefault<FxHasher>>;
pub type FxHashSet<V> = HashSet<V, BuildHasherDefault<FxHasher>>;
#[derive(Default)]
pub struct FxHasher {
    hash: usize,
}
static K: LazyLock<usize> = LazyLock::new(|| {
    ((SystemTime::UNIX_EPOCH.elapsed().unwrap().as_nanos().wrapping_mul(2) + 1)
        & 0xFFFFFFFFFFFFFFFF) as usize
});
impl FxHasher {
    #[inline]
    fn add_to_hash(&mut self, i: usize) {
        self.hash = self.hash.rotate_left(5).bitxor(i).wrapping_mul(*K);
    }
}
impl Hasher for FxHasher {
    #[inline]
    fn write(&mut self, mut bytes: &[u8]) {
        let read_usize = |bytes: &[u8]| u64::from_ne_bytes(
            bytes[..8].try_into().unwrap(),
        );
        let mut hash = FxHasher { hash: self.hash };
        while bytes.len() >= 8 {
            hash.add_to_hash(read_usize(bytes) as usize);
            bytes = &bytes[8..];
        }
        if bytes.len() >= 4 {
            hash.add_to_hash(
                u32::from_ne_bytes(bytes[..4].try_into().unwrap()) as usize,
            );
            bytes = &bytes[4..];
        }
        if bytes.len() >= 2 {
            hash.add_to_hash(
                u16::from_ne_bytes(bytes[..2].try_into().unwrap()) as usize,
            );
            bytes = &bytes[2..];
        }
        if !bytes.is_empty() {
            hash.add_to_hash(bytes[0] as usize);
        }
        self.hash = hash.hash;
    }
    #[inline]
    fn write_u8(&mut self, i: u8) {
        self.add_to_hash(i as usize);
    }
    #[inline]
    fn write_u16(&mut self, i: u16) {
        self.add_to_hash(i as usize);
    }
    #[inline]
    fn write_u32(&mut self, i: u32) {
        self.add_to_hash(i as usize);
    }
    #[inline]
    fn write_u64(&mut self, i: u64) {
        self.add_to_hash(i as usize);
    }
    #[inline]
    fn write_usize(&mut self, i: usize) {
        self.add_to_hash(i);
    }
    #[inline]
    fn finish(&self) -> u64 {
        self.hash as u64
    }
}
}
pub mod iter_ext {
pub mod iters {
use std::iter::{Chain, Enumerate, Filter, Map, Rev, Skip, StepBy, Sum, Take, Zip};
pub trait Iters: IntoIterator + Sized {
    fn iter_enumerate(self) -> Enumerate<Self::IntoIter> {
        self.into_iter().enumerate()
    }
    fn iter_rev(self) -> Rev<Self::IntoIter>
    where
        Self::IntoIter: DoubleEndedIterator,
    {
        self.into_iter().rev()
    }
    fn iter_skip(self, n: usize) -> Skip<Self::IntoIter> {
        self.into_iter().skip(n)
    }
    fn iter_take(self, n: usize) -> Take<Self::IntoIter> {
        self.into_iter().take(n)
    }
    fn iter_chain<V: IntoIterator<Item = Self::Item>>(
        self,
        chained: V,
    ) -> Chain<Self::IntoIter, V::IntoIter> {
        self.into_iter().chain(chained)
    }
    fn iter_zip<V: IntoIterator>(self, other: V) -> Zip<Self::IntoIter, V::IntoIter> {
        self.into_iter().zip(other)
    }
    fn iter_max(self) -> Self::Item
    where
        Self::Item: Ord,
    {
        self.into_iter().max().unwrap()
    }
    fn iter_max_by_key<B, F>(self, f: F) -> Self::Item
    where
        F: FnMut(&Self::Item) -> B,
        B: Ord,
    {
        self.into_iter().max_by_key(f).unwrap()
    }
    fn iter_min(self) -> Self::Item
    where
        Self::Item: Ord,
    {
        self.into_iter().min().unwrap()
    }
    fn iter_min_by_key<B, F>(self, f: F) -> Self::Item
    where
        F: FnMut(&Self::Item) -> B,
        B: Ord,
    {
        self.into_iter().min_by_key(f).unwrap()
    }
    fn iter_sum(self) -> Self::Item
    where
        Self::Item: Sum<Self::Item>,
    {
        Sum::sum(self.into_iter())
    }
    fn iter_map<F, T>(self, f: F) -> Map<Self::IntoIter, F>
    where
        F: FnMut(Self::Item) -> T,
    {
        self.into_iter().map(f)
    }
    fn iter_all(self, f: impl FnMut(Self::Item) -> bool) -> bool {
        self.into_iter().all(f)
    }
    fn iter_any(self, f: impl FnMut(Self::Item) -> bool) -> bool {
        self.into_iter().any(f)
    }
    fn iter_step_by(self, step: usize) -> StepBy<Self::IntoIter> {
        self.into_iter().step_by(step)
    }
    fn iter_filter<F: FnMut(&Self::Item) -> bool>(
        self,
        f: F,
    ) -> Filter<Self::IntoIter, F> {
        self.into_iter().filter(f)
    }
    fn iter_fold<Acc, F>(self, init: Acc, f: F) -> Acc
    where
        F: FnMut(Acc, Self::Item) -> Acc,
    {
        self.into_iter().fold(init, f)
    }
    fn iter_reduce<F>(self, f: F) -> Option<Self::Item>
    where
        F: FnMut(Self::Item, Self::Item) -> Self::Item,
    {
        self.into_iter().reduce(f)
    }
    fn iter_position<P>(self, predicate: P) -> Option<usize>
    where
        P: FnMut(Self::Item) -> bool,
    {
        self.into_iter().position(predicate)
    }
    fn iter_find(self, val: Self::Item) -> Option<usize>
    where
        Self::Item: PartialEq,
    {
        self.into_iter().position(|x| x == val)
    }
    fn iter_count(self, val: Self::Item) -> usize
    where
        Self::Item: PartialEq,
    {
        self.into_iter().filter(|x| *x == val).count()
    }
}
impl<U> Iters for U
where
    U: IntoIterator,
{}
}
pub mod min_max {
use crate::algo_lib::collections::min_max::MinimMaxim;
pub trait IterMinMaxPos<'a, T: Ord + 'a>: 'a
where
    &'a Self: IntoIterator<Item = T>,
{
    fn max_position(&'a self) -> usize {
        let mut res = None;
        let mut val = None;
        for (i, cur) in self.into_iter().enumerate() {
            if val.maxim(cur) {
                res = Some(i);
            }
        }
        res.unwrap()
    }
    fn min_position(&'a self) -> usize {
        let mut res = None;
        let mut val = None;
        for (i, cur) in self.into_iter().enumerate() {
            if val.minim(cur) {
                res = Some(i);
            }
        }
        res.unwrap()
    }
}
impl<'a, T: Ord + 'a, I: ?Sized + 'a> IterMinMaxPos<'a, T> for I
where
    &'a I: IntoIterator<Item = T>,
{}
}
}
pub mod min_max {
pub trait MinimMaxim<Rhs = Self>: PartialOrd + Sized {
    fn minim(&mut self, other: Rhs) -> bool;
    fn maxim(&mut self, other: Rhs) -> bool;
}
impl<T: PartialOrd> MinimMaxim for T {
    fn minim(&mut self, other: Self) -> bool {
        if other < *self {
            *self = other;
            true
        } else {
            false
        }
    }
    fn maxim(&mut self, other: Self) -> bool {
        if other > *self {
            *self = other;
            true
        } else {
            false
        }
    }
}
impl<T: PartialOrd> MinimMaxim<T> for Option<T> {
    fn minim(&mut self, other: T) -> bool {
        match self {
            None => {
                *self = Some(other);
                true
            }
            Some(v) => v.minim(other),
        }
    }
    fn maxim(&mut self, other: T) -> bool {
        match self {
            None => {
                *self = Some(other);
                true
            }
            Some(v) => v.maxim(other),
        }
    }
}
}
pub mod slice_ext {
pub mod bounds {
use std::ops::{Bound, RangeBounds};
pub trait Bounds<T: PartialOrd> {
    fn lower_bound(&self, el: &T) -> usize;
    fn upper_bound(&self, el: &T) -> usize;
    fn bin_search(&self, el: &T) -> Option<usize>;
    fn more(&self, el: &T) -> usize;
    fn more_or_eq(&self, el: &T) -> usize;
    fn less(&self, el: &T) -> usize {
        self.lower_bound(el)
    }
    fn less_or_eq(&self, el: &T) -> usize {
        self.upper_bound(el)
    }
    fn inside<'a>(&self, bounds: impl RangeBounds<&'a T>) -> usize
    where
        T: 'a;
}
impl<T: PartialOrd> Bounds<T> for [T] {
    fn lower_bound(&self, el: &T) -> usize {
        let mut left = 0;
        let mut right = self.len();
        while left < right {
            let mid = left + ((right - left) >> 1);
            if &self[mid] < el {
                left = mid + 1;
            } else {
                right = mid;
            }
        }
        left
    }
    fn upper_bound(&self, el: &T) -> usize {
        let mut left = 0;
        let mut right = self.len();
        while left < right {
            let mid = left + ((right - left) >> 1);
            if &self[mid] <= el {
                left = mid + 1;
            } else {
                right = mid;
            }
        }
        left
    }
    fn bin_search(&self, el: &T) -> Option<usize> {
        let at = self.lower_bound(el);
        if at == self.len() || &self[at] != el { None } else { Some(at) }
    }
    fn more(&self, el: &T) -> usize {
        self.len() - self.upper_bound(el)
    }
    fn more_or_eq(&self, el: &T) -> usize {
        self.len() - self.lower_bound(el)
    }
    fn inside<'a>(&self, bounds: impl RangeBounds<&'a T>) -> usize
    where
        T: 'a,
    {
        let to = match bounds.end_bound() {
            Bound::Included(el) => self.less_or_eq(el),
            Bound::Excluded(el) => self.less(el),
            Bound::Unbounded => self.len(),
        };
        let from = match bounds.start_bound() {
            Bound::Included(el) => self.less(el),
            Bound::Excluded(el) => self.less_or_eq(el),
            Bound::Unbounded => 0,
        };
        to - from
    }
}
}
pub mod indices {
use std::ops::Range;
pub trait Indices {
    fn indices(&self) -> Range<usize>;
}
impl<T> Indices for [T] {
    fn indices(&self) -> Range<usize> {
        0..self.len()
    }
}
}
}
pub mod vec_ext {
pub mod inc_dec {
use crate::algo_lib::numbers::num_traits::algebra::{AdditionMonoidWithSub, One};
pub trait IncDec {
    #[must_use]
    fn inc(self) -> Self;
    #[must_use]
    fn dec(self) -> Self;
}
impl<T: AdditionMonoidWithSub + One> IncDec for T {
    fn inc(self) -> Self {
        self + T::one()
    }
    fn dec(self) -> Self {
        self - T::one()
    }
}
impl<T: AdditionMonoidWithSub + One> IncDec for Vec<T> {
    fn inc(mut self) -> Self {
        self.iter_mut().for_each(|i| *i += T::one());
        self
    }
    fn dec(mut self) -> Self {
        self.iter_mut().for_each(|i| *i -= T::one());
        self
    }
}
impl<T: AdditionMonoidWithSub + One> IncDec for Vec<Vec<T>> {
    fn inc(mut self) -> Self {
        self.iter_mut().for_each(|v| v.iter_mut().for_each(|i| *i += T::one()));
        self
    }
    fn dec(mut self) -> Self {
        self.iter_mut().for_each(|v| v.iter_mut().for_each(|i| *i -= T::one()));
        self
    }
}
impl<T: AdditionMonoidWithSub + One, U: AdditionMonoidWithSub + One> IncDec
for Vec<(T, U)> {
    fn inc(mut self) -> Self {
        self.iter_mut()
            .for_each(|(i, j)| {
                *i += T::one();
                *j += U::one();
            });
        self
    }
    fn dec(mut self) -> Self {
        self.iter_mut()
            .for_each(|(i, j)| {
                *i -= T::one();
                *j -= U::one();
            });
        self
    }
}
impl<T: AdditionMonoidWithSub + One, U: AdditionMonoidWithSub + One, V> IncDec
for Vec<(T, U, V)> {
    fn inc(mut self) -> Self {
        self.iter_mut()
            .for_each(|(i, j, _)| {
                *i += T::one();
                *j += U::one();
            });
        self
    }
    fn dec(mut self) -> Self {
        self.iter_mut()
            .for_each(|(i, j, _)| {
                *i -= T::one();
                *j -= U::one();
            });
        self
    }
}
impl<T: AdditionMonoidWithSub + One, U: AdditionMonoidWithSub + One, V, W> IncDec
for Vec<(T, U, V, W)> {
    fn inc(mut self) -> Self {
        self.iter_mut()
            .for_each(|(i, j, ..)| {
                *i += T::one();
                *j += U::one();
            });
        self
    }
    fn dec(mut self) -> Self {
        self.iter_mut()
            .for_each(|(i, j, ..)| {
                *i -= T::one();
                *j -= U::one();
            });
        self
    }
}
impl<T: AdditionMonoidWithSub + One, U: AdditionMonoidWithSub + One, V, W, X> IncDec
for Vec<(T, U, V, W, X)> {
    fn inc(mut self) -> Self {
        self.iter_mut()
            .for_each(|(i, j, ..)| {
                *i += T::one();
                *j += U::one();
            });
        self
    }
    fn dec(mut self) -> Self {
        self.iter_mut()
            .for_each(|(i, j, ..)| {
                *i -= T::one();
                *j -= U::one();
            });
        self
    }
}
impl<T: AdditionMonoidWithSub + One, U: AdditionMonoidWithSub + One> IncDec for (T, U) {
    fn inc(mut self) -> Self {
        self.0 += T::one();
        self.1 += U::one();
        self
    }
    fn dec(mut self) -> Self {
        self.0 -= T::one();
        self.1 -= U::one();
        self
    }
}
}
}
}
pub mod graph {
use crate::algo_lib::collections::dsu::DSU;
use crate::algo_lib::graph::edges::bi_edge::BiEdge;
use crate::algo_lib::graph::edges::edge::Edge;
use crate::algo_lib::graph::edges::edge_trait::{BidirectionalEdgeTrait, EdgeTrait};
use std::ops::{Index, IndexMut};




















#[derive(Clone)]
pub struct Graph<E: EdgeTrait> {
    edges: Vec<Vec<E>>,
    edge_count: usize,
}
impl<E: EdgeTrait> Graph<E> {
    pub fn new(vertex_count: usize) -> Self {
        Self {
            edges: vec![Vec::new(); vertex_count],
            edge_count: 0,
        }
    }
    pub fn add_edge(&mut self, (from, mut edge): (usize, E)) -> usize {
        let to = edge.to();
        assert!(to < self.vertex_count());
        let direct_id = self.edges[from].len();
        edge.set_id(self.edge_count);
        self.edges[from].push(edge);
        if E::REVERSABLE {
            let rev_id = self.edges[to].len();
            self.edges[from][direct_id].set_reverse_id(rev_id);
            let mut rev_edge = self.edges[from][direct_id].reverse_edge(from);
            rev_edge.set_id(self.edge_count);
            rev_edge.set_reverse_id(direct_id);
            self.edges[to].push(rev_edge);
        }
        self.edge_count += 1;
        direct_id
    }
    pub fn add_vertices(&mut self, cnt: usize) {
        self.edges.resize(self.edges.len() + cnt, Vec::new());
    }
    pub fn clear(&mut self) {
        self.edge_count = 0;
        for ve in self.edges.iter_mut() {
            ve.clear();
        }
    }
    pub fn vertex_count(&self) -> usize {
        self.edges.len()
    }
    pub fn edge_count(&self) -> usize {
        self.edge_count
    }
    pub fn degrees(&self) -> Vec<usize> {
        self.edges.iter().map(|v| v.len()).collect()
    }
}
impl<E: BidirectionalEdgeTrait> Graph<E> {
    pub fn is_tree(&self) -> bool {
        if self.edge_count + 1 != self.vertex_count() {
            false
        } else {
            self.is_connected()
        }
    }
    pub fn is_forest(&self) -> bool {
        let mut dsu = DSU::new(self.vertex_count());
        for i in 0..self.vertex_count() {
            for e in self[i].iter() {
                if i <= e.to() && !dsu.union(i, e.to()) {
                    return false;
                }
            }
        }
        true
    }
    pub fn is_connected(&self) -> bool {
        let mut dsu = DSU::new(self.vertex_count());
        for i in 0..self.vertex_count() {
            for e in self[i].iter() {
                dsu.union(i, e.to());
            }
        }
        dsu.set_count() == 1
    }
}
impl<E: EdgeTrait> Index<usize> for Graph<E> {
    type Output = [E];
    fn index(&self, index: usize) -> &Self::Output {
        &self.edges[index]
    }
}
impl<E: EdgeTrait> IndexMut<usize> for Graph<E> {
    fn index_mut(&mut self, index: usize) -> &mut Self::Output {
        &mut self.edges[index]
    }
}
impl Graph<Edge<()>> {
    pub fn with_edges(n: usize, edges: &[(usize, usize)]) -> Self {
        let mut graph = Self::new(n);
        for &(from, to) in edges {
            graph.add_edge(Edge::new(from, to));
        }
        graph
    }
}
impl<P: Clone> Graph<Edge<P>> {
    pub fn with_edges_with_payload(n: usize, edges: &[(usize, usize, P)]) -> Self {
        let mut graph = Self::new(n);
        for (from, to, p) in edges.iter() {
            graph.add_edge(Edge::with_payload(*from, *to, p.clone()));
        }
        graph
    }
}
impl Graph<BiEdge<()>> {
    pub fn with_biedges(n: usize, edges: &[(usize, usize)]) -> Self {
        let mut graph = Self::new(n);
        for &(from, to) in edges {
            graph.add_edge(BiEdge::new(from, to));
        }
        graph
    }
}
impl<P: Clone> Graph<BiEdge<P>> {
    pub fn with_biedges_with_payload(n: usize, edges: &[(usize, usize, P)]) -> Self {
        let mut graph = Self::new(n);
        for (from, to, p) in edges.iter() {
            graph.add_edge(BiEdge::with_payload(*from, *to, p.clone()));
        }
        graph
    }
}
pub mod edge_distances {
use crate::algo_lib::collections::iter_ext::iters::Iters;
use crate::algo_lib::collections::iter_ext::min_max::IterMinMaxPos;
use crate::algo_lib::graph::edges::edge_trait::{BidirectionalEdgeTrait, EdgeTrait};
use crate::algo_lib::graph::Graph;
use std::collections::VecDeque;
pub trait EdgeAlgos {
    fn edge_distances(&self, source: usize) -> Vec<u32>;
}
pub trait BiEdgeAlgos: EdgeAlgos {
    fn centers(&self) -> Vec<usize>;
    fn diameter(&self) -> usize;
}
impl<E: EdgeTrait> EdgeAlgos for Graph<E> {
    fn edge_distances(&self, source: usize) -> Vec<u32> {
        let mut dist = vec![u32::MAX; self.vertex_count()];
        dist[source] = 0;
        let mut q = VecDeque::new();
        q.push_back(source);
        while !q.is_empty() {
            let cur = q.pop_front().unwrap();
            for e in self[cur].iter() {
                let next = e.to();
                if dist[next] == u32::MAX {
                    dist[next] = dist[cur] + 1;
                    q.push_back(next);
                }
            }
        }
        dist
    }
}
impl<E: BidirectionalEdgeTrait> BiEdgeAlgos for Graph<E> {
    fn centers(&self) -> Vec<usize> {
        debug_assert!(self.is_tree());
        if self.vertex_count() == 0 {
            return Vec::new();
        }
        let d0 = self.edge_distances(0);
        let first = d0.max_position();
        let d1 = self.edge_distances(first);
        let second = d1.max_position();
        let d2 = self.edge_distances(second);
        let mut res = Vec::new();
        let r1 = d1[second] / 2;
        let r2 = (d1[second] + 1) / 2;
        for (i, (d1, d2)) in d1.iter().zip(d2.iter()).enumerate() {
            if *d1 == r1 && *d2 == r2 || *d1 == r2 && *d2 == r1 {
                res.push(i);
            }
        }
        res
    }
    fn diameter(&self) -> usize {
        debug_assert!(self.is_tree());
        let d0 = self.edge_distances(0);
        let first = d0.max_position();
        let d1 = self.edge_distances(first);
        d1.iter_max() as usize
    }
}
}
pub mod edges {
pub mod bi_edge {
use crate::algo_lib::graph::edges::bi_edge_trait::BiEdgeTrait;
use crate::algo_lib::graph::edges::edge_id::{EdgeId, NoId, WithId};
use crate::algo_lib::graph::edges::edge_trait::{BidirectionalEdgeTrait, EdgeTrait};
#[derive(Clone)]
pub struct BiEdgeRaw<Id: EdgeId, P> {
    to: u32,
    id: Id,
    payload: P,
}
impl<Id: EdgeId> BiEdgeRaw<Id, ()> {
    pub fn new(from: usize, to: usize) -> (usize, Self) {
        (
            from,
            Self {
                to: to as u32,
                id: Id::new(),
                payload: (),
            },
        )
    }
}
impl<Id: EdgeId, P> BiEdgeRaw<Id, P> {
    pub fn with_payload(from: usize, to: usize, payload: P) -> (usize, Self) {
        (from, Self::with_payload_impl(to, payload))
    }
    fn with_payload_impl(to: usize, payload: P) -> BiEdgeRaw<Id, P> {
        Self {
            to: to as u32,
            id: Id::new(),
            payload,
        }
    }
}
impl<Id: EdgeId, P: Clone> BidirectionalEdgeTrait for BiEdgeRaw<Id, P> {}
impl<Id: EdgeId, P: Clone> EdgeTrait for BiEdgeRaw<Id, P> {
    type Payload = P;
    const REVERSABLE: bool = true;
    fn to(&self) -> usize {
        self.to as usize
    }
    fn id(&self) -> usize {
        self.id.id()
    }
    fn set_id(&mut self, id: usize) {
        self.id.set_id(id);
    }
    fn reverse_id(&self) -> usize {
        panic!("no reverse id")
    }
    fn set_reverse_id(&mut self, _: usize) {}
    fn reverse_edge(&self, from: usize) -> Self {
        Self::with_payload_impl(from, self.payload.clone())
    }
    fn payload(&self) -> &P {
        &self.payload
    }
}
impl<Id: EdgeId, P: Clone> BiEdgeTrait for BiEdgeRaw<Id, P> {}
pub type BiEdge<P> = BiEdgeRaw<NoId, P>;
pub type BiEdgeWithId<P> = BiEdgeRaw<WithId, P>;
}
pub mod bi_edge_trait {
use crate::algo_lib::graph::edges::edge_trait::EdgeTrait;
pub trait BiEdgeTrait: EdgeTrait {}
}
pub mod edge {
use crate::algo_lib::graph::edges::edge_id::{EdgeId, NoId, WithId};
use crate::algo_lib::graph::edges::edge_trait::EdgeTrait;
#[derive(Clone)]
pub struct EdgeRaw<Id: EdgeId, P> {
    to: u32,
    id: Id,
    payload: P,
}
impl<Id: EdgeId> EdgeRaw<Id, ()> {
    pub fn new(from: usize, to: usize) -> (usize, Self) {
        (
            from,
            Self {
                to: to as u32,
                id: Id::new(),
                payload: (),
            },
        )
    }
}
impl<Id: EdgeId, P> EdgeRaw<Id, P> {
    pub fn with_payload(from: usize, to: usize, payload: P) -> (usize, Self) {
        (from, Self::with_payload_impl(to, payload))
    }
    fn with_payload_impl(to: usize, payload: P) -> Self {
        Self {
            to: to as u32,
            id: Id::new(),
            payload,
        }
    }
}
impl<Id: EdgeId, P: Clone> EdgeTrait for EdgeRaw<Id, P> {
    type Payload = P;
    const REVERSABLE: bool = false;
    fn to(&self) -> usize {
        self.to as usize
    }
    fn id(&self) -> usize {
        self.id.id()
    }
    fn set_id(&mut self, id: usize) {
        self.id.set_id(id);
    }
    fn reverse_id(&self) -> usize {
        panic!("no reverse")
    }
    fn set_reverse_id(&mut self, _: usize) {
        panic!("no reverse")
    }
    fn reverse_edge(&self, _: usize) -> Self {
        panic!("no reverse")
    }
    fn payload(&self) -> &P {
        &self.payload
    }
}
pub type Edge<P> = EdgeRaw<NoId, P>;
pub type EdgeWithId<P> = EdgeRaw<WithId, P>;
}
pub mod edge_id {
pub trait EdgeId: Clone {
    fn new() -> Self;
    fn id(&self) -> usize;
    fn set_id(&mut self, id: usize);
}
#[derive(Clone)]
pub struct WithId {
    id: u32,
}
impl EdgeId for WithId {
    fn new() -> Self {
        Self { id: 0 }
    }
    fn id(&self) -> usize {
        self.id as usize
    }
    fn set_id(&mut self, id: usize) {
        self.id = id as u32;
    }
}
#[derive(Clone)]
pub struct NoId {}
impl EdgeId for NoId {
    fn new() -> Self {
        Self {}
    }
    fn id(&self) -> usize {
        panic!("Id called on no id")
    }
    fn set_id(&mut self, _: usize) {}
}
}
pub mod edge_trait {
pub trait EdgeTrait: Clone {
    type Payload;
    const REVERSABLE: bool;
    fn to(&self) -> usize;
    fn id(&self) -> usize;
    fn set_id(&mut self, id: usize);
    fn reverse_id(&self) -> usize;
    fn set_reverse_id(&mut self, reverse_id: usize);
    #[must_use]
    fn reverse_edge(&self, from: usize) -> Self;
    fn payload(&self) -> &Self::Payload;
}
pub trait BidirectionalEdgeTrait: EdgeTrait {}
}
}
}
pub mod io {
pub mod input {
use std::fs::File;
use std::io::{Read, Stdin};
use std::mem::MaybeUninit;
enum InputSource {
    Stdin(Stdin),
    File(File),
    Slice,
    Delegate(Box<dyn Read + Send>),
}
pub struct Input {
    input: InputSource,
    buf: Vec<u8>,
    at: usize,
    buf_read: usize,
    eol: bool,
}
macro_rules! read_impl {
    ($t:ty, $read_name:ident, $read_vec_name:ident) => {
        pub fn $read_name (& mut self) -> $t { self.read() } pub fn $read_vec_name (& mut
        self, len : usize) -> Vec <$t > { self.read_vec(len) }
    };
    ($t:ty, $read_name:ident, $read_vec_name:ident, $read_pair_vec_name:ident) => {
        read_impl!($t, $read_name, $read_vec_name); pub fn $read_pair_vec_name (& mut
        self, len : usize) -> Vec < ($t, $t) > { self.read_vec(len) }
    };
}
impl Input {
    const DEFAULT_BUF_SIZE: usize = 4096;
    pub fn slice(input: &[u8]) -> Self {
        Self {
            input: InputSource::Slice,
            buf: input.to_vec(),
            at: 0,
            buf_read: input.len(),
            eol: true,
        }
    }
    pub fn stdin() -> Self {
        Self {
            input: InputSource::Stdin(std::io::stdin()),
            buf: vec![0; Self::DEFAULT_BUF_SIZE],
            at: 0,
            buf_read: 0,
            eol: true,
        }
    }
    pub fn file(file: File) -> Self {
        Self {
            input: InputSource::File(file),
            buf: vec![0; Self::DEFAULT_BUF_SIZE],
            at: 0,
            buf_read: 0,
            eol: true,
        }
    }
    pub fn delegate(reader: impl Read + Send + 'static) -> Self {
        Self {
            input: InputSource::Delegate(Box::new(reader)),
            buf: vec![0; Self::DEFAULT_BUF_SIZE],
            at: 0,
            buf_read: 0,
            eol: true,
        }
    }
    pub fn get(&mut self) -> Option<u8> {
        if self.refill_buffer() {
            let res = self.buf[self.at];
            self.at += 1;
            if res == b'\r' {
                self.eol = true;
                if self.refill_buffer() && self.buf[self.at] == b'\n' {
                    self.at += 1;
                }
                return Some(b'\n');
            }
            self.eol = res == b'\n';
            Some(res)
        } else {
            None
        }
    }
    pub fn peek(&mut self) -> Option<u8> {
        if self.refill_buffer() {
            let res = self.buf[self.at];
            Some(if res == b'\r' { b'\n' } else { res })
        } else {
            None
        }
    }
    pub fn skip_whitespace(&mut self) {
        while let Some(b) = self.peek() {
            if !b.is_ascii_whitespace() {
                return;
            }
            self.get();
        }
    }
    pub fn next_token(&mut self) -> Option<Vec<u8>> {
        self.skip_whitespace();
        let mut res = Vec::new();
        while let Some(c) = self.get() {
            if c.is_ascii_whitespace() {
                break;
            }
            res.push(c);
        }
        if res.is_empty() { None } else { Some(res) }
    }
    pub fn is_exhausted(&mut self) -> bool {
        self.peek().is_none()
    }
    pub fn is_empty(&mut self) -> bool {
        self.skip_whitespace();
        self.is_exhausted()
    }
    pub fn read<T: Readable>(&mut self) -> T {
        T::read(self)
    }
    pub fn read_vec<T: Readable>(&mut self, size: usize) -> Vec<T> {
        let mut res = Vec::with_capacity(size);
        for _ in 0..size {
            res.push(self.read());
        }
        res
    }
    pub fn read_char(&mut self) -> u8 {
        self.skip_whitespace();
        self.get().unwrap()
    }
    read_impl!(u32, read_unsigned, read_unsigned_vec);
    read_impl!(u64, read_u64, read_u64_vec);
    read_impl!(usize, read_size, read_size_vec, read_size_pair_vec);
    read_impl!(i32, read_int, read_int_vec, read_int_pair_vec);
    read_impl!(i64, read_long, read_long_vec, read_long_pair_vec);
    read_impl!(i128, read_i128, read_i128_vec);
    fn refill_buffer(&mut self) -> bool {
        if self.at == self.buf_read {
            self.at = 0;
            self.buf_read = match &mut self.input {
                InputSource::Stdin(stdin) => stdin.read(&mut self.buf).unwrap(),
                InputSource::File(file) => file.read(&mut self.buf).unwrap(),
                InputSource::Delegate(reader) => reader.read(&mut self.buf).unwrap(),
                InputSource::Slice => 0,
            };
            self.buf_read != 0
        } else {
            true
        }
    }
    pub fn is_eol(&self) -> bool {
        self.eol
    }
}
pub trait Readable {
    fn read(input: &mut Input) -> Self;
}
impl Readable for u8 {
    fn read(input: &mut Input) -> Self {
        input.read_char()
    }
}
impl<T: Readable> Readable for Vec<T> {
    fn read(input: &mut Input) -> Self {
        let size = input.read();
        input.read_vec(size)
    }
}
impl<T: Readable, const SIZE: usize> Readable for [T; SIZE] {
    fn read(input: &mut Input) -> Self {
        unsafe {
            let mut res = MaybeUninit::<[T; SIZE]>::uninit();
            for i in 0..SIZE {
                let ptr: *mut T = (*res.as_mut_ptr()).as_mut_ptr();
                ptr.add(i).write(input.read::<T>());
            }
            res.assume_init()
        }
    }
}
macro_rules! read_integer {
    ($($t:ident)+) => {
        $(impl Readable for $t { fn read(input : & mut Input) -> Self { input
        .skip_whitespace(); let mut c = input.get().unwrap(); let sgn = match c { b'-' =>
        { c = input.get().unwrap(); true } b'+' => { c = input.get().unwrap(); false } _
        => false, }; let mut res = 0; loop { assert!(c.is_ascii_digit()); res *= 10; let
        d = (c - b'0') as $t; if sgn { res -= d; } else { res += d; } match input.get() {
        None => break, Some(ch) => { if ch.is_ascii_whitespace() { break; } else { c =
        ch; } } } } res } })+
    };
}
read_integer!(i8 i16 i32 i64 i128 isize u16 u32 u64 u128 usize);
macro_rules! tuple_readable {
    ($($name:ident)+) => {
        impl <$($name : Readable),+> Readable for ($($name,)+) { fn read(input : & mut
        Input) -> Self { ($($name ::read(input),)+) } }
    };
}
tuple_readable! {
    T
}
tuple_readable! {
    T U
}
tuple_readable! {
    T U V
}
tuple_readable! {
    T U V X
}
tuple_readable! {
    T U V X Y
}
tuple_readable! {
    T U V X Y Z
}
tuple_readable! {
    T U V X Y Z A
}
tuple_readable! {
    T U V X Y Z A B
}
tuple_readable! {
    T U V X Y Z A B C
}
tuple_readable! {
    T U V X Y Z A B C D
}
tuple_readable! {
    T U V X Y Z A B C D E
}
tuple_readable! {
    T U V X Y Z A B C D E F
}
}
pub mod output {
use std::cmp::Reverse;
use std::fs::File;
use std::io::{Stdout, Write};
#[derive(Copy, Clone)]
pub enum BoolOutput {
    YesNo,
    YesNoCaps,
    PossibleImpossible,
    Custom(&'static str, &'static str),
}
impl BoolOutput {
    pub fn output(&self, output: &mut Output, val: bool) {
        (if val { self.yes() } else { self.no() }).write(output);
    }
    fn yes(&self) -> &str {
        match self {
            BoolOutput::YesNo => "Yes",
            BoolOutput::YesNoCaps => "YES",
            BoolOutput::PossibleImpossible => "Possible",
            BoolOutput::Custom(yes, _) => yes,
        }
    }
    fn no(&self) -> &str {
        match self {
            BoolOutput::YesNo => "No",
            BoolOutput::YesNoCaps => "NO",
            BoolOutput::PossibleImpossible => "Impossible",
            BoolOutput::Custom(_, no) => no,
        }
    }
}
enum OutputDest<'s> {
    Stdout(Stdout),
    File(File),
    Buf(&'s mut Vec<u8>),
    Delegate(Box<dyn Write + 's>),
}
pub struct Output<'s> {
    output: OutputDest<'s>,
    buf: Vec<u8>,
    at: usize,
    bool_output: BoolOutput,
    precision: Option<usize>,
    separator: u8,
}
impl<'s> Output<'s> {
    pub fn buf(buf: &'s mut Vec<u8>) -> Self {
        Self::new(OutputDest::Buf(buf))
    }
    pub fn delegate(delegate: impl Write + 'static) -> Self {
        Self::new(OutputDest::Delegate(Box::new(delegate)))
    }
    fn new(output: OutputDest<'s>) -> Self {
        Self {
            output,
            buf: vec![0; Self::DEFAULT_BUF_SIZE],
            at: 0,
            bool_output: BoolOutput::YesNoCaps,
            precision: None,
            separator: b' ',
        }
    }
}
impl Output<'static> {
    pub fn stdout() -> Self {
        Self::new(OutputDest::Stdout(std::io::stdout()))
    }
    pub fn file(file: File) -> Self {
        Self::new(OutputDest::File(file))
    }
}
impl Output<'_> {
    const DEFAULT_BUF_SIZE: usize = 4096;
    pub fn flush(&mut self) {
        if self.at != 0 {
            match &mut self.output {
                OutputDest::Stdout(stdout) => {
                    stdout.write_all(&self.buf[..self.at]).unwrap();
                    stdout.flush().unwrap();
                }
                OutputDest::File(file) => {
                    file.write_all(&self.buf[..self.at]).unwrap();
                    file.flush().unwrap();
                }
                OutputDest::Buf(buf) => buf.extend_from_slice(&self.buf[..self.at]),
                OutputDest::Delegate(delegate) => {
                    delegate.write_all(&self.buf[..self.at]).unwrap();
                    delegate.flush().unwrap();
                }
            }
            self.at = 0;
        }
    }
    pub fn print<T: Writable>(&mut self, s: T) {
        s.write(self);
    }
    pub fn print_line<T: Writable>(&mut self, s: T) {
        self.print(s);
        self.put(b'\n');
    }
    pub fn put(&mut self, b: u8) {
        self.buf[self.at] = b;
        self.at += 1;
        if self.at == self.buf.len() {
            self.flush();
        }
    }
    pub fn print_per_line<T: Writable>(&mut self, arg: &[T]) {
        self.print_per_line_iter(arg.iter());
    }
    pub fn print_iter<T: Writable, I: Iterator<Item = T>>(&mut self, iter: I) {
        let mut first = true;
        for e in iter {
            if first {
                first = false;
            } else {
                self.put(self.separator);
            }
            e.write(self);
        }
    }
    pub fn print_line_iter<T: Writable, I: Iterator<Item = T>>(&mut self, iter: I) {
        self.print_iter(iter);
        self.put(b'\n');
    }
    pub fn print_per_line_iter<T: Writable, I: Iterator<Item = T>>(&mut self, iter: I) {
        for e in iter {
            e.write(self);
            self.put(b'\n');
        }
    }
    pub fn set_bool_output(&mut self, bool_output: BoolOutput) {
        self.bool_output = bool_output;
    }
    pub fn set_precision(&mut self, precision: usize) {
        self.precision = Some(precision);
    }
    pub fn reset_precision(&mut self) {
        self.precision = None;
    }
    pub fn get_precision(&self) -> Option<usize> {
        self.precision
    }
    pub fn separator(&self) -> u8 {
        self.separator
    }
    pub fn set_separator(&mut self, separator: u8) {
        self.separator = separator;
    }
}
impl Write for Output<'_> {
    fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
        let mut start = 0usize;
        let mut rem = buf.len();
        while rem > 0 {
            let len = (self.buf.len() - self.at).min(rem);
            self.buf[self.at..self.at + len].copy_from_slice(&buf[start..start + len]);
            self.at += len;
            if self.at == self.buf.len() {
                self.flush();
            }
            start += len;
            rem -= len;
        }
        Ok(buf.len())
    }
    fn flush(&mut self) -> std::io::Result<()> {
        self.flush();
        Ok(())
    }
}
pub trait Writable {
    fn write(&self, output: &mut Output);
}
impl Writable for &str {
    fn write(&self, output: &mut Output) {
        output.write_all(self.as_bytes()).unwrap();
    }
}
impl Writable for String {
    fn write(&self, output: &mut Output) {
        output.write_all(self.as_bytes()).unwrap();
    }
}
impl Writable for char {
    fn write(&self, output: &mut Output) {
        output.put(*self as u8);
    }
}
impl Writable for u8 {
    fn write(&self, output: &mut Output) {
        output.put(*self);
    }
}
impl<T: Writable> Writable for [T] {
    fn write(&self, output: &mut Output) {
        output.print_iter(self.iter());
    }
}
impl<T: Writable, const N: usize> Writable for [T; N] {
    fn write(&self, output: &mut Output) {
        output.print_iter(self.iter());
    }
}
impl<T: Writable + ?Sized> Writable for &T {
    fn write(&self, output: &mut Output) {
        T::write(self, output)
    }
}
impl<T: Writable> Writable for Vec<T> {
    fn write(&self, output: &mut Output) {
        self.as_slice().write(output);
    }
}
impl Writable for () {
    fn write(&self, _output: &mut Output) {}
}
macro_rules! write_to_string {
    ($($t:ident)+) => {
        $(impl Writable for $t { fn write(& self, output : & mut Output) { self
        .to_string().write(output); } })+
    };
}
write_to_string!(u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize);
macro_rules! tuple_writable {
    ($name0:ident $($name:ident : $id:tt)*) => {
        impl <$name0 : Writable, $($name : Writable,)*> Writable for ($name0, $($name,)*)
        { fn write(& self, out : & mut Output) { self.0.write(out); $(out.put(out
        .separator); self.$id .write(out);)* } }
    };
}
tuple_writable! {
    T
}
tuple_writable! {
    T U : 1
}
tuple_writable! {
    T U : 1 V : 2
}
tuple_writable! {
    T U : 1 V : 2 X : 3
}
tuple_writable! {
    T U : 1 V : 2 X : 3 Y : 4
}
tuple_writable! {
    T U : 1 V : 2 X : 3 Y : 4 Z : 5
}
tuple_writable! {
    T U : 1 V : 2 X : 3 Y : 4 Z : 5 A : 6
}
tuple_writable! {
    T U : 1 V : 2 X : 3 Y : 4 Z : 5 A : 6 B : 7
}
tuple_writable! {
    T U : 1 V : 2 X : 3 Y : 4 Z : 5 A : 6 B : 7 C : 8
}
impl<T: Writable> Writable for Option<T> {
    fn write(&self, output: &mut Output) {
        match self {
            None => (-1).write(output),
            Some(t) => t.write(output),
        }
    }
}
impl Writable for bool {
    fn write(&self, output: &mut Output) {
        let bool_output = output.bool_output;
        bool_output.output(output, *self)
    }
}
impl<T: Writable> Writable for Reverse<T> {
    fn write(&self, output: &mut Output) {
        self.0.write(output);
    }
}
}
}
pub mod misc {
pub mod lazy_lock {
use std::cell::UnsafeCell;
use std::mem::ManuallyDrop;
use std::ops::Deref;
use std::sync::Once;
union Data<T, F> {
    value: ManuallyDrop<T>,
    f: ManuallyDrop<F>,
}
pub struct LazyLock<T, F = fn() -> T> {
    once: Once,
    data: UnsafeCell<Data<T, F>>,
}
impl<T, F: FnOnce() -> T> LazyLock<T, F> {
    #[inline]
    pub const fn new(f: F) -> LazyLock<T, F> {
        LazyLock {
            once: Once::new(),
            data: UnsafeCell::new(Data { f: ManuallyDrop::new(f) }),
        }
    }
    #[inline]
    pub fn force(this: &LazyLock<T, F>) -> &T {
        this.once
            .call_once(|| {
                let data = unsafe { &mut *this.data.get() };
                let f = unsafe { ManuallyDrop::take(&mut data.f) };
                let value = f();
                data.value = ManuallyDrop::new(value);
            });
        unsafe { &(*this.data.get()).value }
    }
}
impl<T, F: FnOnce() -> T> Deref for LazyLock<T, F> {
    type Target = T;
    #[inline]
    fn deref(&self) -> &T {
        LazyLock::force(self)
    }
}
unsafe impl<T: Sync + Send, F: Send> Sync for LazyLock<T, F> {}
}
pub mod test_type {
pub enum TestType {
    Single,
    MultiNumber,
    MultiEof,
}
pub enum TaskType {
    Classic,
    Interactive,
}
}
}
pub mod numbers {
pub mod num_traits {
pub mod algebra {
use crate::algo_lib::numbers::num_traits::invertible::Invertible;
use std::ops::{
    Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Rem, RemAssign, Sub, SubAssign,
};
pub trait Zero {
    fn zero() -> Self;
}
pub trait One {
    fn one() -> Self;
}
pub trait AdditionMonoid: Add<Output = Self> + AddAssign + Zero + Eq + Sized {}
impl<T: Add<Output = Self> + AddAssign + Zero + Eq> AdditionMonoid for T {}
pub trait AdditionMonoidWithSub: AdditionMonoid + Sub<Output = Self> + SubAssign {}
impl<T: AdditionMonoid + Sub<Output = Self> + SubAssign> AdditionMonoidWithSub for T {}
pub trait AdditionGroup: AdditionMonoidWithSub + Neg<Output = Self> {}
impl<T: AdditionMonoidWithSub + Neg<Output = Self>> AdditionGroup for T {}
pub trait MultiplicationMonoid: Mul<Output = Self> + MulAssign + One + Eq + Sized {}
impl<T: Mul<Output = Self> + MulAssign + One + Eq> MultiplicationMonoid for T {}
pub trait IntegerMultiplicationMonoid: MultiplicationMonoid + Div<
        Output = Self,
    > + Rem<Output = Self> + DivAssign + RemAssign {}
impl<
    T: MultiplicationMonoid + Div<Output = Self> + Rem<Output = Self> + DivAssign
        + RemAssign,
> IntegerMultiplicationMonoid for T {}
pub trait MultiplicationGroup: MultiplicationMonoid + Div<
        Output = Self,
    > + DivAssign + Invertible<Output = Self> {}
impl<
    T: MultiplicationMonoid + Div<Output = Self> + DivAssign + Invertible<Output = Self>,
> MultiplicationGroup for T {}
pub trait SemiRing: AdditionMonoid + MultiplicationMonoid {}
impl<T: AdditionMonoid + MultiplicationMonoid> SemiRing for T {}
pub trait SemiRingWithSub: AdditionMonoidWithSub + SemiRing {}
impl<T: AdditionMonoidWithSub + SemiRing> SemiRingWithSub for T {}
pub trait Ring: SemiRing + AdditionGroup {}
impl<T: SemiRing + AdditionGroup> Ring for T {}
pub trait IntegerSemiRing: SemiRing + IntegerMultiplicationMonoid {}
impl<T: SemiRing + IntegerMultiplicationMonoid> IntegerSemiRing for T {}
pub trait IntegerSemiRingWithSub: SemiRingWithSub + IntegerSemiRing {}
impl<T: SemiRingWithSub + IntegerSemiRing> IntegerSemiRingWithSub for T {}
pub trait IntegerRing: IntegerSemiRing + Ring {}
impl<T: IntegerSemiRing + Ring> IntegerRing for T {}
pub trait Field: Ring + MultiplicationGroup {}
impl<T: Ring + MultiplicationGroup> Field for T {}
macro_rules! zero_one_integer_impl {
    ($($t:ident)+) => {
        $(impl Zero for $t { fn zero() -> Self { 0 } } impl One for $t { fn one() -> Self
        { 1 } })+
    };
}
zero_one_integer_impl!(i128 i64 i32 i16 i8 isize u128 u64 u32 u16 u8 usize);
}
pub mod invertible {
pub trait Invertible {
    type Output;
    fn inv(&self) -> Option<Self::Output>;
}
}
}
}
}

Submission Info

Submission Time
Task D - Moving Pieces on Graph
User Egor
Language Rust (rustc 1.70.0)
Score 700
Code Size 50505 Byte
Status AC
Exec Time 93 ms
Memory 36256 KiB

Judge Result

Set Name Sample All
Score / Max Score 0 / 0 700 / 700
Status
AC × 3
AC × 64
Set Name Test Cases
Sample 00_sample_00.txt, 00_sample_01.txt, 00_sample_02.txt
All 00_sample_00.txt, 00_sample_01.txt, 00_sample_02.txt, 01_handmade_00.txt, 01_handmade_01.txt, 01_handmade_02.txt, 01_handmade_03.txt, 01_handmade_04.txt, 01_handmade_05.txt, 01_handmade_06.txt, 02_line_00.txt, 02_line_01.txt, 02_line_02.txt, 03_line_like_00.txt, 03_line_like_01.txt, 03_line_like_02.txt, 03_line_like_03.txt, 03_line_like_04.txt, 03_line_like_05.txt, 03_line_like_06.txt, 03_line_like_07.txt, 03_line_like_08.txt, 03_line_like_09.txt, 03_line_like_10.txt, 03_line_like_11.txt, 03_line_like_12.txt, 03_line_like_13.txt, 03_line_like_14.txt, 03_line_like_15.txt, 03_line_like_16.txt, 03_line_like_17.txt, 03_line_like_18.txt, 03_line_like_19.txt, 03_line_like_20.txt, 03_line_like_21.txt, 03_line_like_22.txt, 03_line_like_23.txt, 04_circle_like_00.txt, 04_circle_like_01.txt, 04_circle_like_02.txt, 04_circle_like_03.txt, 04_circle_like_04.txt, 04_circle_like_05.txt, 04_circle_like_06.txt, 04_circle_like_07.txt, 04_circle_like_08.txt, 04_circle_like_09.txt, 05_dense_00.txt, 05_dense_01.txt, 05_dense_02.txt, 06_random_00.txt, 06_random_01.txt, 06_random_02.txt, 06_random_03.txt, 06_random_04.txt, 06_random_05.txt, 06_random_06.txt, 06_random_07.txt, 06_random_08.txt, 06_random_09.txt, 07_uni_00.txt, 07_uni_01.txt, 07_uni_02.txt, 07_uni_03.txt
Case Name Status Exec Time Memory
00_sample_00.txt AC 1 ms 2012 KiB
00_sample_01.txt AC 1 ms 1940 KiB
00_sample_02.txt AC 1 ms 1808 KiB
01_handmade_00.txt AC 1 ms 2004 KiB
01_handmade_01.txt AC 0 ms 1872 KiB
01_handmade_02.txt AC 1 ms 2076 KiB
01_handmade_03.txt AC 0 ms 1936 KiB
01_handmade_04.txt AC 1 ms 2148 KiB
01_handmade_05.txt AC 64 ms 33140 KiB
01_handmade_06.txt AC 75 ms 35708 KiB
02_line_00.txt AC 3 ms 3432 KiB
02_line_01.txt AC 77 ms 35652 KiB
02_line_02.txt AC 93 ms 35504 KiB
03_line_like_00.txt AC 88 ms 35644 KiB
03_line_like_01.txt AC 82 ms 35640 KiB
03_line_like_02.txt AC 37 ms 14572 KiB
03_line_like_03.txt AC 51 ms 21168 KiB
03_line_like_04.txt AC 25 ms 13540 KiB
03_line_like_05.txt AC 42 ms 19628 KiB
03_line_like_06.txt AC 27 ms 14424 KiB
03_line_like_07.txt AC 68 ms 27452 KiB
03_line_like_08.txt AC 86 ms 36256 KiB
03_line_like_09.txt AC 52 ms 30192 KiB
03_line_like_10.txt AC 26 ms 12372 KiB
03_line_like_11.txt AC 65 ms 27344 KiB
03_line_like_12.txt AC 51 ms 21304 KiB
03_line_like_13.txt AC 66 ms 35748 KiB
03_line_like_14.txt AC 65 ms 33028 KiB
03_line_like_15.txt AC 27 ms 14376 KiB
03_line_like_16.txt AC 57 ms 23656 KiB
03_line_like_17.txt AC 82 ms 35756 KiB
03_line_like_18.txt AC 1 ms 2228 KiB
03_line_like_19.txt AC 1 ms 2112 KiB
03_line_like_20.txt AC 0 ms 2076 KiB
03_line_like_21.txt AC 1 ms 2072 KiB
03_line_like_22.txt AC 1 ms 2028 KiB
03_line_like_23.txt AC 1 ms 2300 KiB
04_circle_like_00.txt AC 85 ms 35608 KiB
04_circle_like_01.txt AC 76 ms 35548 KiB
04_circle_like_02.txt AC 87 ms 35480 KiB
04_circle_like_03.txt AC 79 ms 35688 KiB
04_circle_like_04.txt AC 75 ms 35640 KiB
04_circle_like_05.txt AC 11 ms 9000 KiB
04_circle_like_06.txt AC 11 ms 9000 KiB
04_circle_like_07.txt AC 11 ms 8920 KiB
04_circle_like_08.txt AC 11 ms 9040 KiB
04_circle_like_09.txt AC 11 ms 8944 KiB
05_dense_00.txt AC 14 ms 7908 KiB
05_dense_01.txt AC 3 ms 2760 KiB
05_dense_02.txt AC 7 ms 5020 KiB
06_random_00.txt AC 27 ms 11224 KiB
06_random_01.txt AC 28 ms 11504 KiB
06_random_02.txt AC 44 ms 18240 KiB
06_random_03.txt AC 37 ms 14604 KiB
06_random_04.txt AC 31 ms 11668 KiB
06_random_05.txt AC 46 ms 18416 KiB
06_random_06.txt AC 31 ms 11828 KiB
06_random_07.txt AC 44 ms 17592 KiB
06_random_08.txt AC 44 ms 17964 KiB
06_random_09.txt AC 48 ms 19672 KiB
07_uni_00.txt AC 20 ms 12596 KiB
07_uni_01.txt AC 7 ms 5684 KiB
07_uni_02.txt AC 37 ms 19832 KiB
07_uni_03.txt AC 37 ms 19748 KiB