#include <bits/stdc++.h>
  
using namespace std;
  
#define rep(i,n) REP(i,0,n)
#define REP(i,s,e) for(int i=(s); i<(int)(e); i++)
#define repr(i, n) REPR(i, n, 0)
#define REPR(i, s, e) for(int i=(int)(s-1); i>=(int)(e); i--)
#define pb push_back
#define all(r) r.begin(),r.end()
#define rall(r) r.rbegin(),r.rend()
#define fi first
#define se second
  
typedef long long ll;
typedef vector<int> vi;
typedef vector<ll> vl;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
 
const int INF = 1e9;
const ll MOD = 1e9 + 7;
double EPS = 1e-8;

struct UFT{    //O(loga(n))
    int n;
    vl d, r;
    UFT(int n) : n(n), d(n, -1), r(n, 0){};
    int root(int i){
        if(d[i] < 0) return i;
        return d[i] = root(d[i]);
    }
    bool same(int x, int y){
        return root(x) == root(y);
    }
    bool unite(int x, int y){
        x = root(x);
        y = root(y);
        if(x == y) return false;

        if(r[x] < r[y]) swap(x, y);
        else if(r[x] == r[y]) r[x]++;
        d[x] += d[y];
        d[y] = x;
        return true;
    }
    ll sum(int i){
        return -d[root(i)];
    }
};

const int MAX_N = 1e5+10;
const int MAX_M = 1e5+10;

struct Edge {
    int u, v;
    ll cost;
    bool operator < (const Edge& e) {
        return cost < e.cost;
    }
};

int main(){
    int n, m;
    cin >> n >> m;
    UFT uf(n);
    rep(i, n) {
        int x;
        cin >> x;
        uf.d[i] = -x;
    }
    vector<Edge> es(m);
    rep(i, m) {
        int u, v;
        ll cost;
        cin >> u >> v >> cost;
        --u;
        --v;
        es[i] = {u, v, cost};
    }
    sort(all(es));
    vector<int> crd(m);
    rep(i, m) {
        int u = es[i].u, v = es[i].v;
        ll cost = es[i].cost;
        uf.unite(u, v);
        // cout << u << " " << v << " " << cost << " " << uf.sum(u) << endl;
        if(uf.sum(u) >= cost) crd[i] = 1;
    }
    vector<vector<int>> ids(n);
    rep(i, m) {
        int u = es[i].u, v = es[i].u;
        ids[u].pb(i);
        ids[v].pb(i);
    }
    vector<int> used(m);
    repr(i, m) {
        if(crd[i] == 0 || used[i]) continue;
        int u = es[i].u, v = es[i].v;
        ll cost = es[i].cost;
        used[i] = 1;
        queue<int> q;
        q.push(u);
        q.push(v);
        while(!q.empty()) {
            auto p = q.front();
            q.pop();
            for(auto&& id : ids[p]) {
                if(used[id] || cost < es[id].cost) continue;
                used[id] = true;
                q.push(es[id].u);
                q.push(es[id].v);
            }
        }
    }
    int ans = 0;
    rep(i, m) if(!used[i]) ++ans;
    cout << ans << endl;
    // rep(i, m) cout << " " << used[i];
    // cout << endl;
    // rep(i, m) cout << " " << crd[i];
    // cout << endl;
    return 0;
}