#include <functional>
#include <algorithm>
#include <iostream>
#include <vector>
#include <queue>
using namespace std;
typedef long long ll;
typedef pair<int, int> P;
typedef pair<ll, P> PP;

struct Graph
{
    int n;
    vector<vector<int>> g;
    
    Graph(int n) : n(n){
        g.resize(n);
    }
    
    void init(int n_){
        n = n_;
        g.resize(n_);
    }
    
    void add_edge(int from, int to){
        g[from].push_back(to);
    }
};

Graph g(0);

template <typename G>   //Abel group
struct UnionFind
{
    using F2 = function<G(G, G)>;
    using F1 = function<G(G)>;
    
    const F2 f;
    const F1 inverse;
    
    vector<int> par, rank;
    vector<G> dat;
    vector<int> last;
    
    UnionFind(int n, const F2 f = [](G a, G b){return a + b;}, F1 inv = [](G a){return -a;}) : f(f), inverse(inv){
        par.resize(n);
        rank.resize(n);
        dat.assign(n, 1);
        for(int i = 0; i < n; i++){
            par[i] = i;
            rank[i] = 0;
        }
    }
    
    int find(int i){
        if(i == par[i]) return i;
        return find(par[i]);
    }
    
    bool same(int i, int j){
        return find(i) == find(j);
    }
    
    void unite(int i, int j){
        i = find(i), j = find(j);
        if(i == j) return;
        if(rank[i] < rank[j]){
            par[i] = j;
            dat[j] = f(dat[i], dat[j]);
            last.push_back(i);
            g.add_edge(j, i);
        }
        else{
            par[j] = i;
            dat[i] = f(dat[i], dat[j]);
            if(rank[i] == rank[j]) rank[i]++;
            last.push_back(j);
            g.add_edge(i, j);
        }
    }
    
    G query(int i){
        return dat[find(i)];
    }
    
    void undo(){
        if((int)last.size() == 0) return;
        int i = *(--last.end());
        int j = find(i);
        par[i] = i;
        dat[j] = f(dat[j], inverse(dat[i]));
        last.pop_back();
    }
};

int main()
{
    int n, m;
    cin >> n >> m;
    g.init(n);
    UnionFind<ll> uf(n);
    for(int i = 0; i < n; i++){
        ll x;
        cin >> x;
        uf.dat[i] = x;
    }
    PP p[100002];
    for(int i = 0; i < m; i++){
        int a, b;
        ll y;
        cin >> a >> b >> y;
        a--; b--;
        p[i] = PP(y, P(a, b));
    }
    sort(p, p + m);
    vector<int> v;
    for(int i = 0; i < m; i++){
        int a = p[i].second.first, b = p[i].second.second;
        if(uf.find(a) != uf.find(b)){
            uf.unite(a, b);
            v.push_back(i);
        }
    }
    bool used[100002]{0};
    bool del[100002]{0};
    int ans = 0;
    for(int i = m - 1; i >= 0; i--){
        int a = p[i].second.first;
        if(!used[a]){
            if(uf.query(a) < p[i].first) ans++;
            else{
                queue<int> que;
                que.push(uf.find(a));
                while(que.size()){
                    int u = que.front();
                    que.pop();
                    used[u] = true;
                    for(int v : g.g[u]){
                        if(del[v]) continue;
                        que.push(v);
                    }
                }
            }
        }
        if(*(--v.end()) == i){
            del[*(--uf.last.end())] = true;
            uf.undo();
            v.pop_back();
        }
    }
    cout << ans << endl;
}

Measured memory_bytes: 8048