#pragma GCC optimize("Ofast")
#include<bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>

#define F first
#define S second
#define int long long
#define ll long long
//#define int  unsigned long long
#define pb push_back
#define double long double

using namespace std;
using namespace __gnu_pbds;
typedef  tree< int , null_type, less<int>, rb_tree_tag, tree_order_statistics_node_update> ordered_set;
const int N = 550000;
const int K = 19;
int n, q;
int mod = 998244353;
int  f[N], invf[N], used[N], d[N];
vector < int > g[N];
int p[N], lb[N], rb[N], pr[N], a[N], sz[N], w[N], b[N], c[N], pv[N], pc[N], ww[N], wg[N], cc[N];
vector < pair < int, pair < int, int > > > edges, newedges;
vector < int > events;
const int magic = 350;
int timer, rm[N], tin[N], tout[N], time2;
int gt(int x){
    if (p[x] == x) return x;
    return p[x] = gt(p[x]);
}
void unite(int x, int y){
    x = gt(x);
    y = gt(y);
    int s1 = sz[x];
    int s2 = sz[y];
    if (s1 > s2){
        p[y] = x;
        sz[x] += sz[y];
    } else{
        p[x] = y;
        sz[x] += sz[y];
    }
}
void merg(int x, int y){
    x = gt(x);
    y = gt(y);
    int s1 = sz[x];
    int s2 = sz[y];
    p[y] = x;
    sz[x] += sz[y];
    wg[x] += wg[y];
}
void build(int v, int tl, int tr){
    a[v] = 1;
    if (tl == tr){
        a[v] = 1;
        c[v] = b[tl];
        return;
    }
    int mid = (tl + tr) / 2;;
    build(v + v, tl, mid);
    build(v + v + 1, mid + 1, tr);
    c[v] = c[v + v] + c[v + v + 1];
    if (a[v + v] == a[v + v + 1] && a[v + v] != 0) a[v] = a[v + v];
}
void push(int v){
    if (a[v] != 0)
        a[v + v] = a[v + v + 1] = a[v];
    a[v] = 0;
}
void update(int v, int tl, int tr, int x, int y, int l, int r){
    if (l > r || (a[v] != 0 && a[v] != y)) return;
    if (tl == l && tr == r && a[v] == y){
        a[v] = x;
        return;
    }
    push(v);
    int mid = (tl + tr) / 2;;
    update(v + v, tl, mid, x, y, l, min(mid, r));
    update(v + v + 1, mid + 1, tr, x, y, max(l, mid + 1), r);
    c[v] = c[v + v] + c[v + v + 1];
    if (a[v + v] == a[v + v + 1] && a[v + v] != 0) a[v] = a[v + v];
}
int root(int v, int tl, int tr, int x){
    if (tl == tr) return a[v];
    push(v);
    int mid = (tl + tr) / 2;;
    if (x <= mid) return root(v + v, tl, mid, x);
    else return root(v + v + 1, mid + 1, tr, x);
}
void dfs(int v, int pp = -1){
    timer++;
    time2++;
    tin[v] = time2;
    w[v] += b[v];
    lb[v] = timer;
    used[v] = 1;
    for (auto u: g[v]){
        if (u == pp) continue;
        pr[u] = v;
        dfs(u, v);
        w[v] += w[u];
    }
    rb[v] = timer;
    time2++;
    tout[v] = time2;
}
int getsum(int v, int tl, int tr, int x, int l, int r){
    if (l > r || (a[v] != 0 && a[v] != x)) return 0;
   // cout << tl << " " << tr << " " << x << "  " << l << " " << r << endl;
    if (a[v] == x && tl == l && tr == r){
        return c[v];
    }
    push(v);
    int mid = (tl + tr) / 2;;
    return getsum(v + v, tl, mid, x, l, min(mid, r)) +
    getsum(v + v + 1, mid + 1, tr, x, max(l, mid + 1), r);
    if (a[v + v] == a[v + v + 1] && a[v + v] != 0) a[v] = a[v + v];
}
int root(int v){
    for (auto i: events){
        if (tin[i] >= tin[rm[v]] && tout[i] <= tout[rm[v]] && tin[i] <= tin[v] && tout[i] >= tout[v]) rm[v] = i;
    }
    return rm[v];
}
void calcroot(){
    events.clear();
    queue < pair < int, int > > q;
    q.push({1, 1});
    while(!q.empty()){
        auto it = q.front();
        q.pop();
        int v = it.F;
        int x = rm[it.S];
        if (cc[v]) x = v;
        rm[v] = x;
        for (auto u: g[v]){
            if (u != it.S){
                q.push({u, v});
            }
        }
    }
}
main(){
    ios_base::sync_with_stdio(0);
    cin.tie(0);
   // freopen("input.txt", "r", stdin);
    int n, m;
    cin >> n >> m;
    for (int i = 1; i <= n; i++) cin >> b[i];
    for (int i = 1; i <= m; i++){
        int v1, v2, w;
        cin >> v1 >> v2 >> w;
        edges.pb({w, {v1, v2}});
    }
    sort(edges.begin(), edges.end());
    for (int i = 1; i <= n; i++){
        p[i] = i;
        sz[i] = 1;
    }
    for (auto i: edges){
        int u = i.S.S;
        int v = i.S.F;
        if (gt(u) != gt(v)){
            unite(u, v);
            g[u].pb(v);
            g[v].pb(u);
            newedges.pb({i.F, {v, u}});
         //   cout << u << " " << v << endl;
        }
    }
    reverse(edges.begin(), edges.end());
    sort(newedges.begin(), newedges.end());
    for (int i = 1; i <= n; i++){
        wg[i] = b[i];
        sz[i] = 1;
        p[i] = i;
    }
    int cnt = n;
    int tt = 0;
    pr[1] = 1;
    dfs(1);
    for (auto i: newedges){
        int u = i.S.F;
        int v = i.S.S;
        if (pr[u] == v) swap(u, v);
        u = gt(u);
        if (v != gt(v)) assert(0);
        cnt--;
        pv[cnt] = wg[u];
        pc[cnt] = wg[v];
        merg(u, v);
        tt = wg[u];
    }
    int ans = 0;
    cnt = 0;
  //  cout << w[1] << endl;
    ww[1] = tt;
    cc[1] = 1;
    for (int i = 1; i <= n; i++) rm[i] = 1;
    for (auto i: edges){
        if (events.size() > magic) calcroot();
        int u = i.S.F;
        int v = i.S.S;
        int r = root(v);
        int w = ww[r];
        if (pr[u] == v || pr[v] == u) cnt++;
      //  cout << getsum(1, 1, n, 4, lb[4], rb[4]) << endl;
        if (w >= i.F) continue;
        ans++;
        if (u == pr[v]){
            ww[r] = pv[cnt];
            ww[v] = pc[cnt];
            cc[v] = 1;
            events.pb(v);

         //   cout << "v = " << v << " " << lb[v] << " " << rb[v] << endl;
        } else
        if (v == pr[u]){
            ww[r] = pv[cnt];
            ww[u] = pc[cnt];
            cc[u] = 1;
            events.pb(u);
         //   cout << "u = " << u << " " << lb[u] << " " << rb[u] << endl;
        }
    }
    cout << ans;
}


Measured memory_bytes: 63344