// includes {{{
#include<iostream>
#include<iomanip>
#include<algorithm>
#include<vector>
#include<stack>
#include<queue>
#include<map>
#include<set>
#include<tuple>
#include<cmath>
#include<random>
#include<cassert>
// #include<deque>
// #include<multiset>
// #include<bitset>
// #include<cstring>
// #include<bits/stdc++.h>
// }}}
using namespace std;
using ll = long long;

/// --- Union Find {{{ ///
#include <vector>
struct UF {
  int n;
  vector< int > par;
  UF(int n) : n(n), par(n, -1) {}
  int find(int x) { return par[x] < 0 ? x : par[x] = find(par[x]); }
  int size(int x) { return -par[find(x)]; }
  bool same(int a, int b) { return find(a) == find(b); }
  void unite(int a, int b) {
    a = find(a);
    b = find(b);
    if(a == b) return;
    if(par[a] < par[b]) swap(a, b);
    par[b] += par[a];
    par[a] = b;
  }
};
/// }}}--- ///


const int N = 1e5;
vector<int> g[N];

int edges[N];
ll w[N];

int n, m;
int main() {
  ios::sync_with_stdio(false), cin.tie(0);
  cin >> n >> m;
  using P = tuple<int, int, int>;
  vector<P> v;
  for(int i = 0; i < n; i++) cin >> w[i];
  for(int i = 0; i < m; i++) {
    int a, b, c; cin >> a >> b >> c;
    a--; b--;
    v.emplace_back(c, a, b);
  }
  sort(begin(v), end(v));
  UF uf(n);
  int ans = 0;
  for(int i = 0; i < m; i++) {
    int c, a, b;
    tie(c, a, b) = v[i];
    a = uf.find(a);
    b = uf.find(b);
    if(a != b) {
      ll newval = w[a] + w[b];
      ll newedge = edges[a] + edges[b];
      uf.unite(a, b);
      a = uf.find(a);
      w[a] = newval;
      edges[a] = newedge;
    }
    edges[a]++;
    if(w[a] >= c) ans += edges[a], edges[a] = 0;
  }
  cout << m - ans << endl;
  return 0;
}
