#include<bits/stdc++.h>
#define REP(i,m) for(int i=0;i<(m);++i)
#define REPN(i,m,in) for(int i=(in);i<(m);++i)
#define ALL(t) (t).begin(),(t).end()
#define CLR(a) memset((a),0,sizeof(a))
#define pb push_back
#define mp make_pair
#define fr first
#define sc second

using namespace std;


#ifdef DEB
#define dump(x)  cerr << #x << " = " << (x) << endl
#define prl cerr<<"called:"<< __LINE__<<endl
#define dumpR(x) cerr<<"\x1b[31m"<<#x<<" = " <<(x)<<"\x1b[39m"<<endl
#define dumpY(x) cerr<<"\x1b[33m"<<#x<<" = " <<(x)<<"\x1b[39m"<<endl
#define dumpG(x) cerr<<"\x1b[32m"<<#x<<" = " <<(x)<<"\x1b[39m"<<endl
template<class T> void debug(T a,T b){ for(;a!=b;++a) cerr<<*a<<' ';cerr<<endl;}
#else
#define dump(x) ;
#define dumpR(x) ;
#define dumpY(x) ;
#define dumpG(x) ;
#define prl ;
template<class T> void debug(T a,T b){ ;}
#endif

template<class T> bool chmin(T& a,const T& b) {
  if(a>b) {
    a=b;
    return true;
  }
  return false;
}
template<class T> bool chmax(T& a,const T& b) {
  if(a<b){
    a=b;
    return true;
  }
  return false;
}

typedef long long int lint;
typedef pair<int,int> pi;

namespace std{
  template<class S,class T>
  ostream &operator <<(ostream& out,const pair<S,T>& a){
    out<<'('<<a.fr<<','<<a.sc<<')';
    return out;
  }
}

//const int INF=5e8;
struct uf{
  static const int MAXN=100005;
  int par[MAXN];
  int size[MAXN];
  void init(){
    memset(par,-1,sizeof(par));
    REP(i,MAXN) size[i]=1;
  }
  int root(int a){
    if(par[a]==-1) return a;
    return par[a]=root(par[a]);
  }
  void unite(int a,int b){
    a=root(a);b=root(b);
    if(a==b) return;
    if(size[a]<size[b]) swap(a,b);

    par[b]=a;
    size[a]+=size[b];
  }
  bool same(int a,int b){
    return root(a)==root(b);
  }
};

uf u;
int n,m;
vector<int> g[100005];
pair<int,pi> es[100005],es2[100005],es3[100005];
lint ar[100005];


struct segtree{
  lint val[1100000];
  int n;
  void init(int n_){
    n=1;
    while(n<n_) n<<=1;
    CLR(val);
  }
  lint query(int a,int b,int i,int l,int r){
    if(a<=l && r<=b) return val[i];
    if(b<=l || r<=a) return 0;
    int md=(l+r)>>1;
    return query(a,b,i*2+1,l,md)+query(a,b,i*2+2,md,r);
  }
  lint query(int a,int b){
    return query(a,b,0,0,n);
  }
  void add(int k,lint a){
    k+=n-1;
    val[k]+=a;
    while(k){
      k=(k-1)/2;
      val[k]+=a;
    }
  }
};

segtree wseg,mseg;

int par[20][100005];
int dep[100005];
int vis[100005],fin[100005],cnt;

void prep(int v,int p,int d=0){
  par[0][v]=p;
  vis[v]=cnt++;
  dep[v]=d;
  for(auto to:g[v]) if(to!=p){
    prep(to,v,d+1);
  }
  fin[v]=cnt++;
}
bool mark[100005];
int main(){
  cin>>n>>m;
  REP(i,n) cin>>ar[i];
  REP(i,m){
    int a,b,c;scanf("%d%d%d",&a,&b,&c);--a;--b;
    es[i]={c,{a,b}};
  }
  sort(es,es+m);

  u.init();
  int m2=0,m3=0;
  prl;
  REP(i,m){
    int a=es[i].sc.fr,b=es[i].sc.sc,c=es[i].fr;
    if(!u.same(a,b)){
      es2[m2++]={c,{a,b}};
      u.unite(a,b);
      g[a].pb(b);
      g[b].pb(a);
      dump(a);dump(b);dump(c);
    }else{
      es3[m3++]={c,{a,b}};
    }
  }
  prl;
  prep(0,-1);
  prl;

  REP(i,19) REP(j,n){
    if(par[i][j]==-1) par[i+1][j]=par[i][j];
    else par[i+1][j]=par[i][par[i][j]];
  }
  prl;
  assert(m2==n-1);
  reverse(es2,es2+n-1);

  wseg.init(n*2);
  mseg.init(n*2);
  prl;

  REP(i,n){
    wseg.add(vis[i],ar[i]);
  }
  auto getp=[&](int v){
    for(int i=19;i>=0;--i) if(~par[i][v]){
      int to=par[i][v];
      dump(to);dump(v);
      dump(vis[to]);dump(vis[v]);
      int tmp=mseg.query(vis[to]+1,vis[v]+1);
      assert(tmp>=0);
      dump(tmp);
      if(tmp==0){
        v=to;
      }
    }
    return v;
  };

  prl;
  auto calc=[&](int v){
    int p=getp(v);
    if(mark[v]) assert(p==v);
    dump(v);dump(p);
    dump(vis[p]);dump(fin[p]);

    return wseg.query(vis[p],fin[p]);
  };

  int res=0;
  REP(i,n-1){
    int a=es2[i].sc.fr,b=es2[i].sc.sc,c=es2[i].fr;
    if(par[0][a]==b) swap(a,b);
    dump(a);dump(b);
    lint tmp=calc(a);
    dump(tmp);
    if(calc(a)<c){
      prl;
      mseg.add(vis[b],1);
      mseg.add(fin[b],-1);

      mark[b]=1;
      lint sub=calc(b);
      dumpR(sub);
      wseg.add(fin[b],-sub);
      int p=getp(a);
      if(~par[0][p]){
        wseg.add(vis[par[0][p]],sub);
      }
      ++res;
    }
  }
  prl;
  auto same=[&](int a,int b){
    if(dep[a]<dep[b]) swap(a,b);
    int dif=dep[a]-dep[b];
    for(int i=19;i>=0;--i){
      if(dif>>i&1){
        int to=par[i][a];
        if(mseg.query(vis[to]+1,vis[a]+1)>0) return false;
        a=to;
      }
    }
    for(int i=19;i>=0;--i) if(~par[i][a]){
      int to1=par[i][a],to2=par[i][b];
      if(to1!=to2){
        if(mseg.query(vis[to1]+1,vis[a]+1)>0 || mseg.query(vis[to2]+1,vis[b]+1)>0) return false;
        a=to1;
        b=to2;
      }
    }
    int p=par[0][a];
    if(!mark[a] && !mark[b]) return true;
    return false;
  };

  REP(i,m3){
    int c=es3[i].fr,a=es3[i].sc.fr,b=es3[i].sc.sc;
    dump(a);dump(b);dump(c);
    dump(same(a,b));
    if(same(a,b) && calc(a)>=c) {
      ;
    }else{
      ++res;
    }

  }
  cout<<res<<endl;
  return 0;
}





Measured memory_bytes: 42752