#include <bits/stdc++.h>
#define rep(i,n) for(int i=0;i<(int)(n);i++)
#define rep1(i,n) for(int i=1;i<=(int)(n);i++)
#define all(c) c.begin(),c.end()
#define pb push_back
#define fs first
#define sc second
#define show(x) cout << #x << " = " << (x) << endl
#define chmin(x,y) x=min(x,y)
#define chmax(x,y) x=max(x,y)
using namespace std;
template<class S,class T> ostream& operator<<(ostream& o,const pair<S,T> &p){
	return o<<"("<<p.fs<<","<<p.sc<<")";
}
template<class T> ostream& operator<<(ostream& o,const vector<T> &vc){
	o<<"{";
	for(const T& v:vc) o<<v<<",";
	o<<"}";
	return o;
}
using ll = long long;
template<class T> using V = vector<T>;
template<class T> using VV = vector<vector<T>>;

struct UnionFind{
	vector<int> par,rank,cnt;
	V<ll> sum;
	UnionFind(int N){
		par.assign(N,0);
		rank.assign(N,0);
		cnt.assign(N,0);
		sum.assign(N,0);
		rep(i,N) par[i]=i;
	}
	int find(int x){
		if(par[x]==x) return x;
		return par[x]=find(par[x]);
	}
	bool same(int x,int y){
		return find(x)==find(y);
	}
	void unite(int x,int y){
		x=find(x),y=find(y);
		if(x==y) return;
		if(rank[x]<rank[y]) swap(x,y);

		//x becomes root
		par[y]=x;
		sum[x] += sum[y];
		cnt[x] += cnt[y];
		if(rank[x]==rank[y]) rank[x]++;
	}
};
int N,M;
V<int> X,Y,A,B;

int main(){
	cin>>N>>M;
	X.resize(N);
	Y.resize(M);
	A.resize(M);
	B.resize(M);
	rep(i,N) cin>>X[i];
	{
		using P = pair<int,int>;
		using PP = pair<int,P>;
		V<PP> es;
		rep(i,M){
			int a,b,c;
			cin>>a>>b>>c;
			a--,b--;
			es.push_back(PP(c,P(a,b)));
		}
		sort(all(es));
		rep(i,M) A[i] = es[i].sc.fs, B[i] = es[i].sc.sc, Y[i] = es[i].fs;
	}
	UnionFind UF(N);
	rep(i,N) UF.sum[i] = X[i];

	int use = 0;
	rep(t,M){
		UF.unite(A[t],B[t]);
		int r = UF.find(A[t]);
		UF.cnt[r]++;
		if(UF.sum[r] >= Y[t]){
			use += UF.cnt[r];
			UF.cnt[r] = 0;
		}
	}
	cout<<M-use<<endl;
}