#![allow(unused_imports, unused_macros, unknown_lints)] use std::collections::*; use std::f64::*; use std::cmp::*; use std::cmp::Ordering::*; macro_rules! dump {($($e:expr), +) => {println!(concat!($(stringify!($e), " = {:?}\n"), +), $($e), +)}} macro_rules! max {($e0:expr, $($e:expr), +) => {{let mut r = $e0; $(r = max(r, $e);)+ r}}} macro_rules! min {($e0:expr, $($e:expr), +) => {{let mut r = $e0; $(r = min(r, $e);)+ r}}} macro_rules! freq {($v:expr) => {{let mut h = HashMap::new(); for x in $v {*h.entry(x).or_insert(0) += 1} h}}} fn main() { let (n,m) = get::tuple::(); let xs = get::vec::(); let es = get::tuples::(m); let g = Graph::new_nonlabeled(n, &es); let is_kadomatsu = |v| { let ps = g.path(v, 2); ps.into_iter().any(|p| { let (v1,v2,v3) = (xs[p[0]-1], xs[p[1]-1], xs[p[2]-1]); v1!=v2&&v2!=v3&&v1!=v3 && (v2v1&&v2>v3) }) }; let ans = if (1..n).into_iter().any(is_kadomatsu) {"YES"} else {"NO"}; println!("{}", ans) } struct Graph { size: usize, adj: Vec> } impl Clone for Graph { fn clone(&self) -> Graph { Graph { size: self.size, adj: self.adj.clone() } } } #[allow(dead_code)] impl Graph { fn new_nonlabeled(n: usize, edges: &[(usize, usize)]) -> Graph { let edges = edges.iter().map(|&(a,b)|(a,b,1)).collect::>(); Graph::new_labeled(n, &edges) } fn new_labeled(n: usize, edges: &[(usize, usize, isize)]) -> Graph { let mut g: Vec> = vec![vec![]; n+1]; for &(a, b, c) in edges { g[a].push((b,c)); g[b].push((a,c)); // delete for digraph } Graph {size: n, adj: g} } fn edges(&self) -> Vec<(usize, usize, isize)> { let mut buf = vec![]; for (i, next) in self.adj.iter().enumerate() { for &(j, x) in next { buf.push((i, j, x)) } } buf } fn extract(&self, p: F) -> Vec where F: Fn(usize) -> bool { (1..self.size+1).into_iter().filter(|&v|p(v)).collect() } fn degree(&self, v: usize) -> usize { self.adj[v].len() } fn is_adjacent(&self, u: usize, v: usize) -> bool { self.adj[u].iter().any(|&(w,_)|w==v) || self.adj[v].iter().any(|&(w,_)|w==u) } fn is_connected(&self) -> bool { self.dfs(1).len() == self.size } fn is_hitofude(&self) -> bool { let deg_odd = self.adj.iter().filter(|vs|vs.len()%2==1).count(); deg_odd == 0 || deg_odd == 2 } fn path(&self, v: usize, n: usize) -> Vec> { fn go(g: &Graph, v: usize, n: usize, mut acc: Vec, buf: &mut Vec>) { if n == 0 {buf.push(acc.clone()); return} for &(w,_) in &g.adj[v] { acc.push(w); go(g, w, n-1, acc.clone(), buf); let _ = acc.pop(); } } let mut buf = vec![]; let acc = vec![v]; go(self, v, n, acc.clone(), &mut buf); buf } fn bellman_ford(&self, s: usize) -> Vec { const INF: isize = std::isize::MAX >> 1; let edges = self.edges(); let mut bf: Vec = vec![INF; self.size]; bf[s] = 0; for _ in 1 .. self.size { for &(v, w, c) in &edges { bf[w] = std::cmp::min(bf[w], bf[v]+c) } } bf } fn dijkstra(&self, s: usize) -> Vec { use std::collections::BinaryHeap; const INF: isize = std::isize::MAX; let mut dk: Vec = vec![INF; self.size]; dk[s] = 0; let mut pq = BinaryHeap::new(); pq.push((0,s)); while let Some((acc,v)) = pq.pop() { let acc = -acc; for &(w,c) in &self.adj[v] { let cand = acc + c; if cand < dk[w] { dk[w] = cand; pq.push((-cand,w)); } } } dk } fn warshall_floyd(&self) -> Vec> { const INF: isize = std::isize::MAX >> 1; let mut wf: Vec> = vec![vec![INF; self.size+1]; self.size+1]; for i in 1 .. self.size+1 {wf[i][i] = 0} for (next, i) in self.adj.iter().zip(0..) { for &(j, x) in next { wf[i][j] = x } } for k in 1 .. self.size+1 { for i in 1 .. self.size+1 { for j in 1 .. self.size+1 { wf[i][j] = std::cmp::min(wf[i][j], wf[i][k] + wf[k][j]); } } } wf } fn coloring2(&self) -> Option<(Vec, Vec)> { fn paint(v: usize, p: bool, g: &Graph, cv: &mut Vec>) -> bool { match cv[v] { None => { let next = &g.adj[v]; cv[v] = Some(p); next.iter().all(|&(w,_)|paint(w,!p,g,cv))}, Some(q) => {q == p} } } let mut canvas: Vec> = vec![None; self.size+1]; let ans = paint(1, false, self, &mut canvas); let bs = canvas.iter().enumerate().filter(|&(_,&v)|v==Some(false)).map(|(i,_)|i).collect::>(); let ws = canvas.iter().enumerate().filter(|&(_,&v)|v==Some(true)).map(|(i,_)|i).collect::>(); if ans {Some((bs,ws))} else {None} } fn dfs(&self, s: usize) -> Vec { fn go(g: &Graph, current: usize, mut path: &mut Vec, mut visited: &mut Vec) { for &(next, _) in &g.adj[current] { if visited[next] { continue } else { visited[next] = true; path.push(next); go(&g, next, &mut path, &mut visited) } } } let mut path = vec![s]; let mut visited = vec![false; self.size+1]; visited[s] = true; go(&self, s, &mut path, &mut visited); path } fn bfs(&self, v: usize) -> Vec { use std::collections::VecDeque; let mut q = VecDeque::new(); let mut buf = vec![]; let mut vd = vec![false; self.size+1]; vd[v] = true; q.push_back(v); while let Some(w) = q.pop_front() { buf.push(w); for &(next,_) in self.adj[w].iter() { if !vd[next] { q.push_back(next); vd[next] = true } } } buf } fn ultimate(&self, v: usize) -> usize { use std::collections::VecDeque; let mut q = VecDeque::new(); let mut dist = 0; let mut vd = vec![false; self.size+1]; vd[v] = true; q.push_back((v,dist)); while let Some((w, d)) = q.pop_front() { dist = std::cmp::max(dist, d); for &(next,_) in self.adj[w].iter() { if !vd[next] { q.push_back((next, d+1)); vd[next] = true } } } dist } fn cut(&mut self, v: usize, w: usize) { self.adj[v].retain(|&(t,_)| t != w); self.adj[w].retain(|&(t,_)| t != v); } } #[allow(dead_code)] mod get { use std::io::*; use std::str::*; use std::process::*; pub fn val() -> T { let mut buf = String::new(); let s = stdin(); s.lock().read_line(&mut buf).ok(); if buf.is_empty() {println!("No input"); exit(0)} buf.trim_right().parse::().ok().unwrap() } pub fn vals(n: usize) -> Vec { let mut vec: Vec = vec![]; for _ in 0 .. n { vec.push(val()); } vec } pub fn tuple() -> (T1, T2) { let mut buf = String::new(); let s = stdin(); s.lock().read_line(&mut buf).ok(); if buf.is_empty() {println!("No input"); exit(0)} let mut it = buf.trim_right().split_whitespace(); let x = it.next().unwrap().parse::().ok().unwrap(); let y = it.next().unwrap().parse::().ok().unwrap(); (x, y) } pub fn tuples(n: usize) -> Vec<(T1, T2)> { let mut vec: Vec<(T1, T2)> = vec![]; for _ in 0 .. n { vec.push(tuple()); } vec } pub fn tuple3() -> (T1, T2, T3) { let mut buf = String::new(); let s = stdin(); s.lock().read_line(&mut buf).ok(); if buf.is_empty() {println!("No input"); exit(0)} let mut it = buf.trim_right().split_whitespace(); let x = it.next().unwrap().parse::().ok().unwrap(); let y = it.next().unwrap().parse::().ok().unwrap(); let z = it.next().unwrap().parse::().ok().unwrap(); (x, y, z) } pub fn tuple3s(n: usize) -> Vec<(T1, T2, T3)> { let mut vec: Vec<(T1, T2, T3)> = vec![]; for _ in 0 .. n { vec.push(tuple3()); } vec } pub fn vec() -> Vec { let mut buf = String::new(); let s = stdin(); s.lock().read_line(&mut buf).ok(); if buf.is_empty() {println!("No input"); exit(0)} buf.trim_right().split_whitespace().map(|t| t.parse::().ok().unwrap()).collect() } pub fn mat(h: usize) -> Vec> { let mut mat = vec![]; for _ in 0 .. h { mat.push(vec()); } mat } pub fn chars() -> Vec { let mut buf = String::new(); let s = stdin(); s.lock().read_line(&mut buf).ok(); if buf.is_empty() {println!("No input"); exit(0)} buf.trim_right().chars().collect() } } #[allow(dead_code)] mod put { use std::string::*; pub fn vec(vec: &Vec, sep: &str) { let out = vec.iter().map(|e| e.to_string()).collect::>().as_slice().join(sep); println!("{}", out); } pub fn mat(mat: &Vec>, sep: &str) { for v in mat { vec(v, sep); } } }