#[allow(unused_macros)]
macro_rules! input {
    (source = $s:expr, $($r:tt)*) => {
        let mut iter = $s.split_whitespace();
        let mut next = || { iter.next().unwrap() };
        input_inner!{next, $($r)*}
    };
    ($($r:tt)*) => {
        let stdin = std::io::stdin();
        let mut bytes = std::io::Read::bytes(std::io::BufReader::new(stdin.lock()));
        let mut next = move || -> String{
            bytes
                .by_ref()
                .map(|r|r.unwrap() as char)
                .skip_while(|c|c.is_whitespace())
                .take_while(|c|!c.is_whitespace())
                .collect()
        };
        input_inner!{next, $($r)*}
    };
}

#[allow(unused_macros)]
macro_rules! input_inner {
    ($next:expr) => {};
    ($next:expr, ) => {};

    ($next:expr, $var:ident : $t:tt $($r:tt)*) => {
        let $var = read_value!($next, $t);
        input_inner!{$next $($r)*}
    };

    ($next:expr, mut $var:ident : $t:tt $($r:tt)*) => {
        let mut $var = read_value!($next, $t);
        input_inner!{$next $($r)*}
    };
}

#[allow(unused_macros)]
macro_rules! read_value {
    ($next:expr, ( $($t:tt),* )) => {
        ( $(read_value!($next, $t)),* )
    };

    ($next:expr, [ $t:tt ; $len:expr ]) => {
        (0..$len).map(|_| read_value!($next, $t)).collect::<Vec<_>>()
    };

    ($next:expr, chars) => {
        read_value!($next, String).chars().collect::<Vec<char>>()
    };

    ($next:expr, bytes) => {
        read_value!($next, String).into_bytes()
    };

    ($next:expr, usize1) => {
        read_value!($next, usize) - 1
    };

    ($next:expr, $t:ty) => {
        $next().parse::<$t>().expect("Parse error")
    };
}

pub mod union_find {
    pub struct UnionFind(Vec<usize>);

    impl UnionFind {
        pub fn new(n: usize) -> UnionFind {
            UnionFind((0..n).collect())
        }

        pub fn find(&mut self, i: usize) -> usize {
            if self.0[i] == i {
                i
            } else {
                let p = self.0[i];
                self.0[i] = self.find(p);
                self.0[i]
            }
        }

        pub fn union(&mut self, i: usize, j: usize) {
            let ni = self.find(i);
            let nj = self.find(j);
            self.0[ni] = nj;
        }
    }
}

use union_find::UnionFind;

fn main() {
    input! {
        n: usize,
        m: usize,
        x: [i64; n],
        mut es: [(usize1, usize1, i64); m],
    }

    es.sort_by_key(|&(_, _, w)| w);

    let mut uf = UnionFind::new(n);
    let mut sum = x;
    let mut cand = vec![false; m];

    for (i, &(u, v, w)) in es.iter().enumerate() {
        if uf.find(u) != uf.find(v) {
            let s = sum[uf.find(u)] + sum[uf.find(v)];
            uf.union(u, v);
            sum[uf.find(u)] = s;
        }

        if w <= sum[uf.find(u)] {
            cand[i] = true;
        }
    }

    let mut g = vec![vec![]; n];

    for (i, &(u, v, w)) in es.iter().enumerate() {
        g[u].push((v, w, i));
        g[v].push((u, w, i));
    }

    let mut used = vec![false; m];
    let mut visit = vec![false; n];

    for i in (0..m).rev() {
        if used[i] {
            continue;
        }

        if !cand[i] {
            continue;
        }

        rec(es[i].0, es[i].2, &g, &mut visit, &mut used);
    }

    let ans = used.iter().filter(|&b| !b).count();
    println!("{}", ans);
}

fn rec(
    cur: usize,
    w: i64,
    g: &Vec<Vec<(usize, i64, usize)>>,
    visit: &mut Vec<bool>,
    used: &mut Vec<bool>,
) {
    if visit[cur] {
        return;
    }
    visit[cur] = true;

    for &(next, nw, i) in g[cur].iter() {
        if nw > w {
            continue;
        }

        used[i] = true;
        rec(next, w, g, visit, used);
    }
}


Measured memory_bytes: 28924