#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <climits>
#include <cfloat>
#include <map>
#include <utility>
#include <set>
#include <iostream>
#include <memory>
#include <string>
#include <vector>
#include <algorithm>
#include <functional>
#include <sstream>
#include <complex>
#include <stack>
#include <queue>
#include <cstring>

using namespace std;

class UnionFindTree
{
   private:
      int N;
      int *rootnum;
      int *rank;
      int *unionnum;

   public:
      UnionFindTree(int n){
         /*0からn-1までの要素をunionとしてもつ*/
         N = n;
         rootnum = new int[N];
         rank = new int[N];
         unionnum = new int[N];
         for( int i = 0 ; i < N ; i++ ){
            rootnum[i] = i;
            rank[i] = 0;
            unionnum[i] = 1;
         }
      }
      
      int Find( int j ){
         if( rootnum[j] == j ){
            return j;
         }
         else{
            return rootnum[j] = Find(rootnum[j]);
         }
      }

      void Union( int i , int j ){
         int x = Find(i);
         int y = Find(j);
         if( x == y ) return;
         N--;
         if( rank[x] < rank[y] ){
            rootnum[y] = x;
            unionnum[x] += unionnum[y];
         }else{
            rootnum[x] = y;
            unionnum[y] += unionnum[x];
            if( rank[x]==rank[y] ) rank[x]++;
         }
      }

      int Num( int j ){
         /*与えられた要素の入っている集合の要素数を答える*/
         int x = Find(j);
         return unionnum[x];
      }

      int UnionNum(){
         /*集合の数を答える*/
         return N;
      }

      ~UnionFindTree(){
         delete rootnum;
         delete rank;
         delete unionnum;
      }

};


vector<pair<pair<int,int>, int>> edges[100001];
bool used[100001];
bool arrived[100001];
int X[100001];
void dfs(int a, int y){
   arrived[a]=true;
   for(int ei=0; ei<(int)edges[a].size(); ei++){
      int y2 = edges[a][ei].first.first;
      int b = edges[a][ei].first.second;
      int i = edges[a][ei].second;
      if(y2 <= y){
         //cout << a <<"->" <<b << ": "<< y2 << "<" << y << endl;
         used[i]=true;
         if(arrived[b]==false){
            dfs(b, y);
         }
      }
   }
}
int main(){
  int N,M;
  cin >> N >> M;
  for(int i=0;i<N;i++)cin>>X[i];
  vector<pair<int, pair<int,int>>> E;
  for(int i=0;i<M;i++){
     int A,B,Y;
     cin >> A >> B >> Y;
     A--;B--;
     E.push_back(make_pair(Y, make_pair(A,B)));
  }
  sort(E.begin(),E.end());
  for(int i=0; i<M; i++){
     int Y = E[i].first;
     int A = E[i].second.first;
     int B = E[i].second.second;
     edges[A].push_back(make_pair(make_pair(Y,B),i));
     edges[B].push_back(make_pair(make_pair(Y,A),i));
  }
  UnionFindTree uft(N);
  long long cost[N];
  for(int i=0;i<N;i++) cost[i]=X[i];
  bool flag[M];
  memset(flag,false,sizeof(flag));
  for(int i=0;i<M;i++){
     int y = E[i].first;
     int a = E[i].second.first;
     int b = E[i].second.second;
     int ar = uft.Find(a);
     int br = uft.Find(b);
     if(ar!=br){
        uft.Union(a,b);
        int abr = uft.Find(a);
        cost[abr] = cost[ar]+cost[br];
     }
     int abr2 = uft.Find(a);
     if(cost[abr2] >= y ){
        //cout << i <<":"<< y << ":" << a<<"," << b<<endl;
        flag[i]=true;
     }
  }
  memset(used,false,sizeof(used));
  int ans = 0;
  for(int i = M-1 ; i >=0 ; i--){
     int y = E[i].first;
     int a = E[i].second.first;
     if(used[i]==false && flag[i]==true){
        memset(arrived,false,sizeof(arrived));
        dfs(a, y);
     }
     else if(!used[i]){
        //int b = E[i].second.second;
        //cout << "  "<<i <<":" << y << ", "<< a << ", "<< b << endl;
        ans++;
     }
  }
  cout << ans << endl;
  return 0;
}


Measured memory_bytes: 15732