#include <bits/stdc++.h>
typedef long long ll;
#define FOR(i,a,b) for(int i=(a);i<(b);i++)
#define REP(i,a) FOR(i,0,a)
	
using namespace std;
const int MAX_N=1e5,MAX_M=1e5;
int N,M;
ll X[MAX_N];
struct edge{
	int s,t;
	ll cst;
	int inx;
	edge(int s=-1,int t=-1,ll c=0,int i=-1):s(s),t(t),cst(c),inx(i){}
	bool operator < (const edge &e)const{
		return cst<e.cst;
	}
};
struct edge2{
	int to;
	ll cst;
	int inx;
	edge2(int t=-1,ll c=0,int i=-1):to(t),cst(c),inx(i){}
};
edge E[MAX_M];
vector<edge2> G[MAX_N];
int used[MAX_M];
bool koho[MAX_M];
//bool visit[MAX_N];
int par[MAX_N];
ll sm[MAX_N];
int fndpar(int v){
	if(par[v]==v){
		return v;
	}
	return par[v]=fndpar(par[v]);
}
void unite(int s,int t){
	s=fndpar(s);
	t=fndpar(t);
	par[t]=s;
	sm[s]+=sm[t];
}
void dfs(int v,ll c){
//	visit[v]=true;
	for(auto e:G[v]){
		if(e.cst<=c && used[e.inx]==-1){
			used[e.inx]=1;
			dfs(e.to,c);
		}
	}
}
int main(){
	cin>>N>>M;
	REP(i,N)cin>>X[i];
	REP(i,M){
		int a,b;
		ll y;
		cin>>a>>b>>y;
		a--;
		b--;
		E[i]=edge(a,b,y,i);
		G[a].push_back(edge2(b,y,i));
		G[b].push_back(edge2(a,y,i));
	}
	sort(E,E+M);
	REP(i,N){
		par[i]=i;
		sm[i]=X[i];
	}
	REP(i,M){
		auto e=E[i];
		if(fndpar(e.s)!=fndpar(e.t)){
			unite(e.s,e.t);
		}
		if(sm[fndpar(e.s)]>=e.cst){
			koho[e.inx]=true;
		}
	}
	reverse(E,E+M);
	int ans=0;
	memset(used,-1,sizeof(used));
	REP(i,M){
		auto e=E[i];
		if(used[e.inx]!=-1)continue;
		if(koho[e.inx]){
			dfs(e.s,e.cst);
		}else{
			used[e.inx]=0;
			ans++;
		}
	}
	cout<<ans<<endl;
}