use input::input_array; use std::collections::VecDeque; use union_find::UnionFind; fn main() { let [n, m] = input_array::(); let [s, t, k] = input_array::(); let s = s - 1; let t = t - 1; let mut uf = UnionFind::<()>::new(2 * n); let mut g = vec![Vec::new(); n]; for _ in 0..m { let [i, j] = input_array::(); let i = i - 1; let j = j - 1; g[i].push(j); g[j].push(i); uf.union(i, n + j); uf.union(j, n + i); } let dist = calc_dist(s, &g); let ans = if n == 1 { Ans::No } else if n == 2 { match m { 0 => { if s == t { match k % 2 { 0 => { if k == 0 { Ans::Yes } else { Ans::Unknown } } 1 => Ans::No, _ => unreachable!(), } } else { match k % 2 { 0 => Ans::No, 1 => Ans::Unknown, _ => unreachable!(), } } } 1 => { if s == t { match k % 2 { 0 => Ans::Yes, 1 => Ans::No, _ => unreachable!(), } } else { match k % 2 { 0 => Ans::No, 1 => Ans::Yes, _ => unreachable!(), } } } _ => unreachable!(), } } // disjoint else if !uf.same(s, t) && !uf.same(s, t + n) { Ans::Unknown } // same part else if uf.same(s, t) { match k % 2 { 0 => { if k < dist[t] { Ans::Unknown } else { Ans::Yes } } 1 => Ans::No, _ => unreachable!(), } } // other part else { match k % 2 { 0 => Ans::No, 1 => { if k < dist[t] { Ans::Unknown } else { Ans::Yes } } _ => unreachable!(), } }; println!( "{}", match ans { Ans::Yes => "Yes", Ans::No => "No", Ans::Unknown => "Unknown", } ); } #[derive(Clone, Copy)] enum Ans { Yes, No, Unknown, } pub fn calc_dist(start: usize, g: &[Vec]) -> Vec { let mut dist = vec![std::usize::MAX; g.len()]; dist[start] = 0; let mut queue = VecDeque::from(vec![start]); while let Some(x) = queue.pop_front() { for &y in &g[x] { if dist[y] == std::usize::MAX { dist[y] = dist[x] + 1; queue.push_back(y); } } } dist } // input {{{ #[allow(dead_code)] mod input { use std::cell::Cell; use std::convert::TryFrom; use std::io::stdin; use std::io::BufRead; use std::io::BufReader; use std::io::Lines; use std::io::Stdin; use std::str::FromStr; use std::sync::Mutex; use std::sync::Once; type Server = Mutex>>; static ONCE: Once = Once::new(); pub struct Lazy(Cell>); unsafe impl Sync for Lazy {} fn line() -> String { static SYNCER: Lazy = Lazy(Cell::new(None)); ONCE.call_once(|| { SYNCER .0 .set(Some(Mutex::new(BufReader::new(stdin()).lines()))); }); unsafe { (*SYNCER.0.as_ptr()) .as_ref() .unwrap() .lock() .unwrap() .next() .unwrap() .unwrap() } } pub trait ForceFromStr: FromStr { fn force_from_str(s: &str) -> Self; } impl ForceFromStr for T where T: FromStr, E: std::fmt::Debug, { fn force_from_str(s: &str) -> Self { s.parse().unwrap() } } pub fn input_array() -> [T; N] where T: std::fmt::Debug, { <[_; N]>::try_from(input_vec()).unwrap() } pub fn input_vec() -> Vec { line() .split_whitespace() .map(T::force_from_str) .collect::>() } pub fn input() -> T { T::force_from_str(&line()) } } // }}} // union_find {{{ #[allow(dead_code)] mod union_find { use std::fmt::Debug; use std::fmt::Formatter; use std::fmt::Result; use std::iter::repeat_with; use std::marker::PhantomData; use std::mem::replace; use std::mem::swap; use std::mem::take; pub trait Op { type Value: Default; fn singleton() -> Self::Value; fn add_edge(x: &mut Self::Value); fn graft(parent: &mut Self::Value, child: Self::Value); } impl Op for () { type Value = (); fn singleton() -> Self::Value {} fn add_edge(_x: &mut Self::Value) {} fn graft(_parent: &mut Self::Value, _child: Self::Value) {} } impl Op for (T, U) { type Value = (T::Value, U::Value); fn singleton() -> Self::Value { (T::singleton(), U::singleton()) } fn add_edge(x: &mut Self::Value) { T::add_edge(&mut x.0); U::add_edge(&mut x.1); } fn graft(parent: &mut Self::Value, child: Self::Value) { T::graft(&mut parent.0, child.0); U::graft(&mut parent.1, child.1); } } impl Op for (T, U, V) { type Value = (T::Value, U::Value, V::Value); fn singleton() -> Self::Value { (T::singleton(), U::singleton(), V::singleton()) } fn add_edge(x: &mut Self::Value) { T::add_edge(&mut x.0); U::add_edge(&mut x.1); V::add_edge(&mut x.2); } fn graft(parent: &mut Self::Value, child: Self::Value) { T::graft(&mut parent.0, child.0); U::graft(&mut parent.1, child.1); V::graft(&mut parent.2, child.2); } } pub enum EdgeCount {} impl Op for EdgeCount { type Value = usize; fn singleton() -> Self::Value { 0 } fn add_edge(x: &mut Self::Value) { *x += 1; } fn graft(parent: &mut Self::Value, child: Self::Value) { *parent += child + 1 } } pub enum VertexCount {} impl Op for VertexCount { type Value = usize; fn singleton() -> Self::Value { 1 } fn add_edge(_x: &mut Self::Value) {} fn graft(parent: &mut Self::Value, child: Self::Value) { *parent += child } } pub enum HasCycle {} impl Op for HasCycle { type Value = bool; fn singleton() -> Self::Value { false } fn add_edge(x: &mut Self::Value) { *x = true } fn graft(parent: &mut Self::Value, child: Self::Value) { *parent |= child } } #[derive(Clone, Default, Hash, PartialEq)] pub struct UnionFind { parent_or_size: Vec, values: Vec, __marker: PhantomData O>, } impl UnionFind { pub fn new(n: usize) -> Self { Self::from_values(repeat_with(|| O::singleton()).take(n).collect()) } pub fn from_values(values: Vec) -> Self { let n = values.len(); assert!(n <= std::usize::MAX / 2); Self { parent_or_size: vec![-1; n], values, __marker: PhantomData, } } pub fn find_mut(&mut self, mut x: usize) -> usize { assert!(x < self.parent_or_size.len()); let mut p = self.parent_or_size[x]; while 0 <= p { if 0 <= self.parent_or_size[p as usize] { self.parent_or_size[x] = self.parent_or_size[p as usize]; } x = p as usize; p = self.parent_or_size[x]; } x } pub fn find(&self, mut x: usize) -> usize { assert!(x < self.parent_or_size.len()); let mut p = self.parent_or_size[x]; while 0 <= p { x = p as usize; p = self.parent_or_size[x]; } x } pub fn same(&self, x: usize, y: usize) -> bool { self.find(x) == self.find(y) } pub fn is_root(&self, x: usize) -> bool { x == self.find(x) } pub fn get_value(&self, x: usize) -> &O::Value { assert!(x < self.parent_or_size.len()); &self.values[self.find(x)] } pub fn value_mut(&mut self, x: usize) -> &mut O::Value { assert!(x < self.parent_or_size.len()); let x = self.find(x); &mut self.values[x] } pub fn value(&self, x: usize) -> O::Value where O::Value: Copy, { assert!(x < self.parent_or_size.len()); self.values[self.find(x)] } pub fn union(&mut self, mut x: usize, mut y: usize) -> bool { assert!(x < self.parent_or_size.len()); assert!(y < self.parent_or_size.len()); x = self.find_mut(x); y = self.find_mut(y); if x == y { O::add_edge(&mut self.values[x]); false } else { if self.parent_or_size[x] < self.parent_or_size[y] { swap(&mut x, &mut y); } let aug = take(&mut self.values[x]); O::graft(&mut self.values[y], aug); self.parent_or_size[y] += replace(&mut self.parent_or_size[x], y as isize); true } } } impl Debug for UnionFind where O::Value: Debug, { fn fmt(&self, f: &mut Formatter<'_>) -> Result { let n = self.parent_or_size.len(); let mut groups = vec![Vec::new(); n]; for i in 0..n { groups[self.find(i)].push(i); } f.debug_list() .entries( groups .into_iter() .filter(|group| !group.is_empty()) .map(|list| (&self.values[self.find(*list.first().unwrap())], list)), ) .finish() } } } // }}}