#include<bits/stdc++.h>
using namespace std;
using Int = long long;
template<typename T1,typename T2> inline void chmin(T1 &a,T2 b){if(a>b) a=b;}
template<typename T1,typename T2> inline void chmax(T1 &a,T2 b){if(a<b) a=b;}


struct UnionFind{
  Int n;
  vector<Int> r,v,p;
  using P = pair<Int, Int>;
  using T = tuple<Int, Int, Int>;
  map<P, T> st;
  UnionFind(){}
  UnionFind(Int sz,vector<Int> x):n(sz),r(sz,1),v(x),p(sz,0){
    iota(p.begin(),p.end(),0);
  }
  Int find(Int x){
    return (x==p[x]?x:find(p[x]));
  }
  bool same(Int x,Int y){
    return find(x)==find(y);
  }
  void unite(Int x,Int y){
    Int a=x,b=y;
    x=find(x);y=find(y);    
    if(x==y){
      st[P(a,b)]=T(x,y,-1);
      return;
    }
    if(r[x]<r[y]) swap(x,y);
    r[x]+=r[y];
    v[x]+=v[y];
    p[y]=x;
    st[P(a,b)]=T(x,y,v[y]);
  }
  void rollback(Int a,Int b){
    assert(!st.empty());
    Int x,y,z;
    tie(x,y,z)=st[P(a,b)];
    if(z<0) return;
    r[x]-=r[y];
    v[x]-=v[y];
    p[y]=y;
  }
};

//INSERT ABOVE HERE
signed main(){
  Int n,m;
  cin>>n>>m;
  vector<Int> x(n);
  for(Int i=0;i<n;i++) cin>>x[i];

  struct edge{
    Int a,b,y;
    edge(){}
    edge(Int a,Int b,Int y):a(a),b(b),y(y){}
    bool operator<(const edge &e)const{return y<e.y;}
  };

  vector<edge> es;
  for(Int i=0;i<m;i++){
    Int a,b,y;
    cin>>a>>b>>y;
    a--;b--;
    es.emplace_back(a,b,y);
  }

  sort(es.begin(),es.end());
  UnionFind uf(n,x);
  for(auto e:es) uf.unite(e.a,e.b);

  reverse(es.begin(),es.end());
  Int ans=0;
  for(auto e:es){
    Int a=e.a,b=e.b,y=e.y;
    Int r=uf.find(a);
    if(y<=uf.v[r]) continue;
    uf.rollback(a,b);
    ans++;
  }  
  
  cout<<ans<<endl;
  return 0;
}
