//~ while (clock()<=69*CLOCKS_PER_SEC)
//~ #pragma comment(linker, "/stack:200000000")
//~ #pragma GCC optimize("O3")
//~ #pragma GCC optimize("Ofast")
//~ #pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
//~ #pragma GCC optimize("unroll-loops")
#include<bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>

#define pb push_back
#define SZ(x) ((int)(x).size())
#define ALL(x) x.begin(),x.end()
#define all(x) x.begin(),x.end()
#define fi first
#define se second
#define _upgrade ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
#define erase_duplicates(x) sort(all(x)); (x).resize(distance((x).begin(), unique(all(x))));


using namespace std;
using namespace __gnu_pbds;
template<typename T>
using ordered_set = tree<
T,
null_type,
less<T>,
rb_tree_tag,
tree_order_statistics_node_update>;

//X.find_by_order(k); - zwraca iterator na k-ty element (numeracja od zerowego)
//X.order_of_key(k); - zwraca liczbę elementów ostro mniejszych niż k

typedef long long LL;
typedef pair<int,int> PII;
typedef pair<LL,LL> PLL;
typedef vector<PII> VPII;
typedef vector<PLL> VPLL;
typedef vector<LL> VLL;
typedef vector<int> VI;
typedef vector<string> VS;
typedef vector<char> VC;
typedef long double LD;
typedef pair<LD,LD> PLD;
typedef vector<LD> VLD;
typedef vector<PLD> VPLD;

template<class TH> void _dbg(const char *sdbg, TH h){ cerr<<sdbg<<" = "<<h<<endl; }
template<class TH, class... TA> void _dbg(const char *sdbg, TH h, TA... a) {
  while(*sdbg!=',')cerr<<*sdbg++;
  cerr<<" = "<<h<<", "; _dbg(sdbg+1, a...);
}

#ifdef LOCAL
#define dbg(...) _dbg(#__VA_ARGS__, __VA_ARGS__)
#else
#define dbg(...)
#define cerr if(0)cout
#endif

const int maxn = (1e6)+7;
const int maxk = 20;
const int inf = (1e9)+7;
const LL LLinf = ((LL)1e18)+7LL;
const LD eps = 1e-9;
const LL mod = 1e9+7;

// ***************************** CODE ***************************** //

struct edge
{
  int a, b, c;
  int num;
  edge(int A, int B, int C, int NUM)
  {
    a = A;
    b = B;
    c = C;
    num = NUM;
  }

  edge()
  {

  }

  bool operator<(const edge & x)const
  {
    if(c != x.c)
      return c < x.c;
    if(a != x.a)
      return a < x.a;
    return b < x.b;
  }
};

int val[maxn];
int F[maxn];
int r[maxn];
LL suma[maxn];
set<PII> wek[maxn];

int fin(int x)
{
  if(F[x] != x)
    return fin(F[x]);
  return x;
}

vector<vector<int> > zmiany;

void uni(int a, int b, int c)
{
  a = fin(a);
  b = fin(b);
  if(r[a] < r[b])
    swap(a, b);
  if(a != b)
  {
    suma[a] += suma[b];
    r[a] += r[b] + 1;
    F[b] = F[a];
    zmiany.pb({c, a, b});
  }
  else
  {
    r[a]++;
    zmiany.pb({c, a, -1});
  }
}

void cofnij()
{
  assert(SZ(zmiany));
  if(zmiany.back()[2] == -1)
  {
    r[zmiany.back()[1]]--;
    zmiany.pop_back();
    return;
  }
  int a = zmiany.back()[1];
  int b = zmiany.back()[2];
  r[a] -= r[b] + 1;
  suma[a] -= suma[b];
  F[b] = b;
  zmiany.pop_back();
}

set<edge> roz;
set<edge> elo;
edge kraw[maxn];
int vis[maxn];
int numer = 1;

void dfs(int x)
{
  vis[x] = numer;
  for(auto s : wek[x])
    elo.insert(kraw[s.se]);
  for(auto s : wek[x])
    if(vis[s.fi] < numer)
      dfs(s.fi);
}

void usun(edge x)
{
  wek[x.a].erase({x.b, x.num});
  wek[x.b].erase({x.a, x.num});
}

void rek(set<edge> * zb, bool buduj = 0)
{
  if(buduj)
  {
    while(SZ(zmiany))
      cofnij();
    for(auto s : *zb)
      uni(s.a, s.b, s.num);
  }
  // dbg(SZ(*zb), buduj);
  if(SZ(*zb) == 0)
    return ;
  auto it = (*zb).end();
  it--;
  while(SZ(*zb) && suma[fin(it->a)] < it->c)
  {
    // dbg(it->a, it->b, it->c, it->num);
    while(zmiany.back()[0] != it->num)
      cofnij();
    // dbg(it->a, it->b, it->c, it->num);
    assert(SZ(zmiany) > 0);
    cofnij();
    // dbg(it->a, it->b, it->c, it->num);
    if(fin(it->a) == fin(it->b))
    {
      roz.erase(*it);
      usun(*it);
      (*zb).erase(*it);
      if(SZ(*zb) == 0)
        return;
      it = (*zb).end();
      it--;
    }
    else
    {
      roz.erase(*it);
      usun(*it);
      int a = it->a;
      int b = it->b;
      (*zb).erase(*it);
      if(r[fin(a)] < r[fin(b)])
        swap(a, b);
      numer++;
      elo.clear();
      // dfs(b);
      for(auto s : elo)
        (*zb).erase(s);
      auto cnt = elo;
      rek(zb, 0);
      rek(&cnt, 1);
      return;
    }
  }
  return;
}

int main()
{
	_upgrade
  int n, m;
  cin>>n>>m;
  for(int i = 1;i <= n;i++)
  {
    cin>>val[i];
    F[i] = i;
    r[i] = 0;
    suma[i] = val[i];
  }
  set<edge> zb;
  for(int i = 1;i <= m;i++)
  {
    int a, b, c;
    cin>>a>>b>>c;
    wek[a].insert({b, i});
    wek[b].insert({a, i});
    kraw[i] = edge(a, b, c, i);
    roz.insert(edge(a, b, c, i));
    zb.insert(edge(a, b, c, i));
  }
  rek(&zb, 1);
  cout<<m - SZ(roz);
	return 0;
}
