#include <bits/stdc++.h>

using namespace std;

using ll = long long;
using P = pair<int, int>;
using T = tuple<ll, int, int>;

struct UnionFind {
    //各要素が属する集合の代表(根)を管理する
    //もし、要素xが根であればdata[x]は負の値を取り、-data[x]はxが属する集合の大きさに等しい
    vector<int> data;

    UnionFind(int sz) : data(sz, -1) {}

    bool unite(int x, int y) {
        x = find(x);
        y = find(y);
        bool is_union = (x != y);
        if (is_union) {
            if (data[x] > data[y]) swap(x, y);
            data[x] += data[y];
            data[y] = x;
        }
        return is_union;
    }

    int find(int x) {
        if (data[x] < 0) { //要素xが根である
            return x;
        } else {
            data[x] = find(data[x]); //data[x]がxの属する集合の根でない場合、根になるよう更新される
            return data[x];
        }
    }

    bool same(int x, int y) {
        return find(x) == find(y);
    }

    int size(int x) {
        return -data[find(x)];
    }
};

void bfs(int cur, ll lim, vector<int>& used, vector< vector<int> >& g, vector<T>& es) {
    queue<int> q;
    q.push(cur);

    while (!q.empty()) {
        int node = q.front();
        q.pop();

        for (int i : g[node]) {
            if (used[i]) continue;
            if (get<0>(es[i]) > lim) continue;
            used[i] = true;
            q.push((get<1>(es[i]) == node ? get<2>(es[i]) : get<1>(es[i])));
        }
    }
}

int main() {
    cin.tie(0);
    ios::sync_with_stdio(false);
    int n, m;
    cin >> n >> m;
    vector<ll> x(n);
    for (int i = 0; i < n; i++) cin >> x[i];

    vector<int> idxs(m);
    vector<T> es;
    vector< vector<int> > g(n);
    for (int i = 0; i < m; i++) {
        int a, b;
        ll y;
        cin >> a >> b >> y;
        a--; b--;
        g[a].push_back(i);
        g[b].push_back(i);
        idxs[i] = i;
        es.emplace_back(y, a, b);
    }
    sort(idxs.begin(), idxs.end(), [&](const int i1, const int i2){return get<0>(es[i1]) < get<0>(es[i2]);});

    UnionFind uf(n);
    vector<ll> node_sum(n, 0), edge_max(n, 0);
    for (int i = 0; i < n; i++) node_sum[i] = x[i];

    vector<int> cands(m, false);
    for (int i : idxs) {
        ll cost;
        int a, b;
        tie(cost, a, b) = es[i];

        int ra = uf.find(a), rb = uf.find(b);
        uf.unite(a, b);
        int r = uf.find(a);
        if (ra == rb) edge_max[r] = max(edge_max[r], cost);
        else if (r == ra) {
            node_sum[r] = node_sum[ra] + node_sum[rb];
            node_sum[rb] = 0;
            edge_max[r] = max({edge_max[ra], edge_max[rb], cost});
            edge_max[rb] = 0;
        } else {
            node_sum[r] = node_sum[ra] + node_sum[rb];
            node_sum[ra] = 0;
            edge_max[r] = max({edge_max[ra], edge_max[rb], cost});
            edge_max[ra] = 0;
        }

        if (node_sum[r] >= edge_max[r]) {
            cands[i] = true;
        }
    }

    reverse(idxs.begin(), idxs.end());

    vector<int> used(m, false);
    for (int i : idxs) {
        if (!cands[i]) continue;
        if (used[i]) continue;

        ll cost;
        int a, b;
        tie(cost, a, b) = es[i];
        bfs(a, cost, used, g, es);
    }

    int ans = 0;
    for (int i = 0; i < m; i++) ans += !used[i];
    cout << ans << endl;
    return 0;
}

Measured memory_bytes: 11248