#include <bits/stdc++.h>
using namespace std;
template <class T>
void debug(T itr1, T itr2) {
  auto now = itr1;
  while (now < itr2) {
    cout << *now << " ";
    now++;
  }
  cout << endl;
}
const long long MOD = pow(10, 9) + 7;
const long long LLINF = pow(2, 61) - 1;
const int INF = pow(2, 30) - 1;
vector<long long> fac;
void c_fac(int x = pow(10, 6) + 10) {
  fac.resize(x, true);
  for (int i = (int)0; i < (int)x; i++) fac[i] = i ? (fac[i - 1] * i) % MOD : 1;
}
long long inv(long long a, long long m = MOD) {
  long long b = m, x = 1, y = 0;
  while (b != 0) {
    int d = a / b;
    a -= b * d;
    swap(a, b);
    x -= y * d;
    swap(x, y);
  }
  return (x + m) % m;
}
long long nck(long long n, long long k) {
  return fac[n] * inv(fac[k] * fac[n - k] % MOD) % MOD;
}
long long gcd(long long a, long long b) {
  if (a < b) swap(a, b);
  return b == 0 ? a : gcd(b, a % b);
}
long long lcm(long long a, long long b) { return a / gcd(a, b) * b; }
struct UnionFind {
  vector<int> par, s;
  UnionFind(int N) : par(N), s(N) {
    for (int i = (int)0; i < (int)N; i++) {
      par[i] = i;
      s[i] = 1;
    }
  }
  int root(int x) { return par[x] == x ? x : par[x] = root(par[x]); }
  int size(int x) { return par[x] == x ? s[x] : s[x] = size(root(x)); }
  void unite(int x, int y) {
    int rx = root(x), ry = root(y);
    if (rx != ry) {
      s[rx] += s[ry];
      par[ry] = rx;
    }
  }
  bool same(int x, int y) {
    int rx = root(x), ry = root(y);
    return rx == ry;
  }
};
struct edge {
  long long from;
  long long to;
  long long v;
  long long i;
};
vector<vector<edge>> adj;
vector<bool> used_v, used_e;
void dfs(int n, int v) {
  used_v[n] = true;
  for (auto x : adj[n]) {
    if (x.v <= v) {
      if (used_v[x.to]) continue;
      used_e[x.i] = true;
      dfs(x.to, v);
    }
  }
}
int main() {
  int N, M;
  cin >> N >> M;
  UnionFind uf(N);
  for (int i = (int)0; i < (int)N; i++) {
    long long X;
    cin >> X;
    uf.s[i] = X;
  }
  edge e[M];
  adj.resize(N);
  for (int i = (int)0; i < (int)M; i++) {
    long long A, B, Y;
    cin >> A >> B >> Y;
    A--;
    B--;
    e[i] = {A, B, Y, i};
    adj[A].push_back({A, B, Y, i});
    adj[B].push_back({B, A, Y, i});
  }
  sort(e, e + M, [](const edge &x, const edge &y) { return x.v < y.v; });
  used_v.resize(N, false);
  used_e.resize(M, false);
  for (int i = (int)0; i < (int)M; i++) {
    uf.unite(e[i].from, e[i].to);
    if (uf.size(e[i].from) >= e[i].v) used_e[e[i].i] = true;
  }
  for (int i = (int)M - 1; i >= 0; i--)
    if (used_e[e[i].i]) dfs(e[i].from, e[i].v);
  long long result = 0;
  for (int i = (int)0; i < (int)M; i++) result += !used_e[i];
  cout << result << endl;
  return 0;
}
