#include <iostream>
#include <iomanip>
#include <ios> 
#include <vector>
#include <string>
#include <algorithm>
#include <functional>
#include <queue>
#include <stack>
#include <set>
#include <cmath>
#include <bitset>
#include <map>
#define rep(i,n) for(int (i)=0;(i)<(n);(i)++)
#define rep1(i,n) for(int i=1;i<=(int)(n);i++)
#define sz(c) ((int)(c).size())

using namespace std;
typedef long long ll;
typedef vector<int> vi;
typedef vector<ll> vll;
typedef pair<int,int> P;
const int MAX=1e5+5;

int par[MAX];
int rk[MAX];
ll v[MAX],sum[MAX];
int po[MAX];

//初期化
void init(int n){
	for(int i=0;i<n;i++){
		par[i]=i;
		rk[i]=0;
		sum[i]=v[i];
		po[i]=0;
	}
}
//根を求める
int find(int x){
	if(par[x]==x){
		return x;
	}
	else{
		return par[x]=find(par[x]);
	}
}
//xとyの属する集合を併合
int unite(int x,int y,ll c){
  	int d=0;
	x=find(x);
	y=find(y);
	if(x==y){
//      	cout<<sum[x]<<" ";
		if(c<=sum[x]){
			d=1;
		}
		else{
			po[x]++;
		}
		return d;
	}
//  	cout<<sum[x]+sum[y]<<" ";
	
	if(rk[x]<rk[y]){
		par[x]=y;
		sum[y]+=sum[x];
		po[y]+=po[x];
		if(c<=sum[y]){
			d=po[y]+1;
			po[y]=0;
		}
		else{
			po[y]++;
		}
	}
	else{
		par[y]=x;
		if(rk[x]==rk[y])rk[x]++;
		sum[x]+=sum[y];
		po[x]+=po[y];
		if(c<=sum[x]){
			d=po[x]+1;
			po[x]=0;
		}
		else{
			po[x]++;
		}
	}
  	return d;
}
//xとyが同じ集合に属するか判定
bool same(int x,int y){
	return find(x)==find(y);
}

int main(){
	int N,M;
	cin>>N>>M;
	rep(i,N)cin>>v[i];
	multimap<ll,P> edge;
	rep(i,M){
		int a,b;
      	ll y;
		cin>>a>>b>>y;
		a--;b--;
		P p=make_pair(a,b);
		edge.insert(make_pair(y,p));
	}
	
	init(N);
	multimap<ll,P>::iterator ite;
	ite=edge.begin();
  	int ans=0;
	while(ite!=edge.end()){
		ll cost=ite->first;
		P e=ite->second;
		int a=e.first,b=e.second;
//		cout<<a<<" "<<b<<" "<<cost<<" ";
		int ad=unite(a,b,cost);
//      	cout<<ad<<endl;
      	ans+=ad;
		ite++;
	}
	
	cout<<M-ans<<endl;;
}