Problem:
Score : 300 points

Problem Statement

There are N observatories in AtCoder Hill, called Obs. 1, Obs. 2, ..., Obs. N. The elevation of Obs. i is H_i.
There are also M roads, each connecting two different observatories. Road j connects Obs. A_j and Obs. B_j.

Obs. i is said to be good when its elevation is higher than those of all observatories that can be reached from Obs. i using just one road.
Note that Obs. i is also good when no observatory can be reached from Obs. i using just one road.

How many good observatories are there?

Constraints

2 \leq N \leq 10^5

1 \leq M \leq 10^5

1 \leq H_i \leq 10^9

1 \leq A_i,B_i \leq N

A_i \neq B_i

Multiple roads may connect the same pair of observatories.

All values in input are integers.

Input

Input is given from Standard Input in the following format:

N M
H_1 H_2 ... H_N
A_1 B_1
A_2 B_2
:
A_M B_M

Output

Print the number of good observatories.

Sample Input 1

4 3
1 2 3 4
1 3
2 3
2 4

Sample Output 1

2

From Obs. 1, you can reach Obs. 3 using just one road. The elevation of Obs. 1 is not higher than that of Obs. 3, so Obs. 1 is not good.

From Obs. 2, you can reach Obs. 3 and 4 using just one road. The elevation of Obs. 2 is not higher than that of Obs. 3, so Obs. 2 is not good.

From Obs. 3, you can reach Obs. 1 and 2 using just one road. The elevation of Obs. 3 is higher than those of Obs. 1 and 2, so Obs. 3 is good.

From Obs. 4, you can reach Obs. 2 using just one road. The elevation of Obs. 4 is higher than that of Obs. 2, so Obs. 4 is good.

Thus, the good observatories are Obs. 3 and 4, so there are two good observatories.

Sample Input 2

6 5
8 6 9 1 2 1
1 3
4 2
4 3
4 6
4 6

Sample Output 2

3

Solution in Rust (1.42.0) (judge verdict: Accepted)

#![allow(dead_code)]
use crate::scanner::Scanner;
fn main() {
    let mut scan = Scanner::new();
    let n = scan.read::<usize>();
    let m = scan.read::<usize>();
    let h = scan.readn::<i64>(n);
    let mut g = vec![vec![]; n];
    for _ in 0..m {
        let a = scan.read::<usize>() - 1;
        let b = scan.read::<usize>() - 1;
        g[a].push(b);
        g[b].push(a);
    }
    let mut ret = 0;
    'outer: for i in 0..n {
        for &v in &g[i] {
            if h[i] <= h[v] {
                continue 'outer;
            }
        }
        ret += 1;
    }
    println!("{}", ret);
}
mod union_find {
    pub struct Utree {
        n: usize,
        par: Vec<usize>,
        rank: Vec<usize>,
        size: Vec<usize>,
    }
    impl Utree {
        pub fn new(n: usize) -> Utree {
            Utree {
                n: n,
                par: (0..n).collect(),
                rank: vec![0; n],
                size: vec![1; n],
            }
        }
        pub fn find(&mut self, x: usize) -> usize {
            if self.par[x] == x {
                x
            } else {
                let parent = { self.par[x] };
                let ret = self.find(parent);
                self.par[x] = ret;
                ret
            }
        }
        pub fn unite(&mut self, mut x: usize, mut y: usize) {
            x = self.find(x);
            y = self.find(y);
            if x == y {
                return;
            };
            if self.rank[x] < self.rank[y] {
                self.par[x] = y;
                self.size[y] += self.size[x];
            } else {
                self.par[y] = x;
                self.size[x] += self.size[y];
                if self.rank[x] == self.rank[y] {
                    self.rank[x] += 1;
                }
            }
        }
        pub fn is_same(&mut self, mut x: usize, mut y: usize) -> bool {
            x = self.find(x);
            y = self.find(y);
            x == y
        }
        pub fn get_size(&mut self, mut x: usize) -> usize {
            x = self.find(x);
            self.size[x]
        }
        pub fn size(&mut self) -> usize {
            let mut hset = std::collections::HashSet::new();
            for i in 0..self.n {
                hset.insert(self.find(i));
            }
            hset.len()
        }
    }
}
mod scanner {
    use std::io::{stdin, BufReader, Bytes, Read, Stdin};
    use std::str::FromStr;
    pub struct Scanner {
        buf: Bytes<BufReader<Stdin>>,
    }
    impl Scanner {
        pub fn new() -> Scanner {
            Scanner {
                buf: BufReader::new(stdin()).bytes(),
            }
        }
        pub fn read_next<T: FromStr>(&mut self) -> Option<T> {
            let token = self
                .buf
                .by_ref()
                .map(|c| c.unwrap() as char)
                .skip_while(|c| c.is_whitespace())
                .take_while(|c| !c.is_whitespace())
                .collect::<String>();
            token.parse::<T>().ok()
        }
        pub fn read<T: FromStr>(&mut self) -> T {
            self.read_next().unwrap()
        }
        pub fn readn<T: FromStr>(&mut self, n: usize) -> Vec<T> {
            (0..n).map(|_| self.read::<T>()).collect()
        }
        pub fn chars(&mut self) -> Vec<char> {
            self.read::<String>().chars().collect()
        }
    }
}
mod counter {
    use std::collections::HashMap;
    use std::hash::Hash;
    use std::ops::*;
    #[derive(Clone, Debug)]
    pub struct Counter<K: Eq + Hash> {
        pub cnt: HashMap<K, i64>,
        pub d: i64,
    }
    impl<K: Eq + Hash> Counter<K> {
        pub fn new() -> Counter<K> {
            Counter {
                cnt: HashMap::new(),
                d: 0,
            }
        }
        #[doc = " Remove key when the value <= 0"]
        pub fn dec(&mut self, key: K, delta: i64) {
            if self.by_ref(&key) - delta <= 0 {
                self.remove(&key);
            } else {
                *self.cnt.get_mut(&key).unwrap() -= delta;
            }
        }
        pub fn by_ref(&self, key: &K) -> i64 {
            *self.cnt.get(key).unwrap_or(&self.d)
        }
    }
    impl<K: Eq + Hash> Deref for Counter<K> {
        type Target = HashMap<K, i64>;
        fn deref(&self) -> &Self::Target {
            &self.cnt
        }
    }
    impl<K: Eq + Hash> DerefMut for Counter<K> {
        fn deref_mut(&mut self) -> &mut Self::Target {
            &mut self.cnt
        }
    }
    impl<K: Eq + Hash> Index<K> for Counter<K> {
        type Output = i64;
        fn index(&self, index: K) -> &Self::Output {
            self.cnt.get(&index).unwrap_or(&self.d)
        }
    }
    impl<K: Eq + Hash + Clone> IndexMut<K> for Counter<K> {
        fn index_mut(&mut self, index: K) -> &mut i64 {
            if !self.cnt.contains_key(&index) {
                self.cnt.insert(index.clone(), self.d);
            }
            self.cnt.get_mut(&index).unwrap()
        }
    }
    impl<K: Eq + Hash> std::iter::FromIterator<K> for Counter<K> {
        fn from_iter<T: IntoIterator<Item = K>>(iter: T) -> Self {
            let mut cnt = HashMap::new();
            for i in iter {
                *cnt.entry(i).or_insert(0) += 1;
            }
            Counter { cnt, d: 0 }
        }
    }
    impl<T: Eq + Hash + Clone> Add for Counter<T> {
        type Output = Counter<T>;
        fn add(self, other: Counter<T>) -> Counter<T> {
            let mut ret = Counter::new();
            for (k, v) in self.iter().chain(other.iter()) {
                ret[k.clone()] += *v;
            }
            ret
        }
    }
    impl<T: Eq + Hash + Clone> AddAssign for Counter<T> {
        fn add_assign(&mut self, other: Self) {
            *self = self.clone().add(other);
        }
    }
}