#include <bits/stdc++.h>
using namespace std;

long long x[100005];

struct WWUnionFind {
    vector<int> par;
    vector<int> sz;
    vector<long long> wt;
    vector<int> es;

    WWUnionFind(int n=0){
        if(n>0) initialize(n);
    }

    void initialize(int n){
        par.resize(n);
        sz.resize(n);
        wt.resize(n);
        es.resize(n);
        for(int i=0; i<n; i++){
            par[i] = i;
            sz[i] = 1;
            wt[i] = x[i];
            es[i] = 0;
        }
    }

    int find(int x){
        if(par[x] == x){
            return x;
        }else{
            return par[x] = find(par[x]);
        }
    }

    void unite(int x, int y){
        x = find(x);
        y = find(y);
        if(x == y) return;
        if(sz[x] < sz[y]){
            par[x] = y;
            sz[y] += sz[x];
            wt[y] += wt[x];
            es[y] += es[x];
        }else{
            par[y] = x;
            sz[x] += sz[y];
            wt[x] += wt[y];
            es[x] += es[y];
        }
    }

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

    long long weight(int x){
        return wt[find(x)];
    }

    void add_edge(int x){
        x = find(x);
        es[x]++;
    }

    int result_edge(int x){
        x = find(x);
        int ret = es[x];
        es[x] = 0;
        return ret;
    }
};

struct edges
{
	int a;
	int b;
	long long y;

	bool operator<(const edges &cmp) const
	{
		return y<cmp.y;
	}
};

int main(int argc, char const *argv[])
{
	int n,m;
	cin>>n>>m;
	for (int i = 0; i < n; ++i)
	{
		cin>>x[i];
	}
	edges edge[m];
	for (int i = 0; i < m; ++i)
	{
		cin>>edge[i].a>>edge[i].b>>edge[i].y;
		--edge[i].a;--edge[i].b;
	}
	sort(edge,edge+m);
	WWUnionFind uf(n);
	int ans=0;
	for (auto v:edge)
	{
		uf.unite(v.a,v.b);
		uf.add_edge(v.a);
		long long w=uf.weight(v.a);
		if (w>=v.y)
		{
			ans+=uf.result_edge(v.a);
		}
	}
	cout<<m-ans<<endl;
	return 0;
}
