#include <bits/stdc++.h>
using namespace std;
template <class T>
void debug(T a, T b) {
  ;
}
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;
}
namespace std {
template <class S, class T>
ostream& operator<<(ostream& out, const pair<S, T>& a) {
  out << '(' << a.first << ',' << a.second << ')';
  return out;
}
}  // namespace std
struct uf {
  static const int MAXN = 100005;
  int par[MAXN];
  int size[MAXN];
  void init() {
    memset(par, -1, sizeof(par));
    for (int i = 0; i < (MAXN); ++i) 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, pair<int, int> > es[100005], es2[100005], es3[100005];
long long int ar[100005];
struct segtree {
  long long int val[1100000];
  int n;
  void init(int n_) {
    n = 1;
    while (n < n_) n <<= 1;
    memset((val), 0, sizeof(val));
  }
  long long int 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);
  }
  long long int query(int a, int b) { return query(a, b, 0, 0, n); }
  void add(int k, long long int 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;
  for (int i = 0; i < (n); ++i) cin >> ar[i];
  for (int i = 0; i < (m); ++i) {
    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;
  ;
  ;
  for (int i = 0; i < (m); ++i) {
    int a = es[i].second.first, b = es[i].second.second, c = es[i].first;
    if (!u.same(a, b)) {
      es2[m2++] = {c, {a, b}};
      u.unite(a, b);
      g[a].push_back(b);
      g[b].push_back(a);
      ;
      ;
      ;
      ;
      ;
      ;
    } else {
      es3[m3++] = {c, {a, b}};
    }
  };
  ;
  prep(0, -1);
  ;
  ;
  for (int i = 0; i < (19); ++i)
    for (int j = 0; j < (n); ++j) {
      if (par[i][j] == -1)
        par[i + 1][j] = par[i][j];
      else
        par[i + 1][j] = par[i][par[i][j]];
    };
  ;
  assert(m2 == n - 1);
  reverse(es2, es2 + n - 1);
  wseg.init(n * 2);
  mseg.init(n * 2);
  ;
  ;
  for (int i = 0; i < (n); ++i) {
    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];
        ;
        ;
        ;
        ;
        ;
        ;
        ;
        ;
        int tmp = mseg.query(vis[to] + 1, vis[v] + 1);
        assert(tmp >= 0);
        ;
        ;
        if (tmp == 0) {
          v = to;
        }
      }
    return v;
  };
  ;
  ;
  auto calc = [&](int v) {
    int p = getp(v);
    ;
    ;
    ;
    ;
    ;
    ;
    ;
    ;
    return wseg.query(vis[p], fin[p]);
  };
  int res = 0;
  for (int i = 0; i < (n - 1); ++i) {
    int a = es2[i].second.first, b = es2[i].second.second, c = es2[i].first;
    if (par[0][a] == b) swap(a, b);
    ;
    ;
    ;
    ;
    long long int tmp = calc(a);
    ;
    ;
    if (calc(a) < c) {
      ;
      ;
      mseg.add(vis[b], 1);
      mseg.add(fin[b], -1);
      mark[a] = 1;
      long long int sub = calc(b);
      ;
      ;
      wseg.add(fin[b], -sub);
      ++res;
    }
  };
  ;
  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[p]) return true;
    return false;
  };
  for (int i = 0; i < (m3); ++i) {
    int c = es3[i].first, a = es3[i].second.first, b = es3[i].second.second;
    ;
    ;
    ;
    ;
    ;
    ;
    ;
    ;
    if (same(a, b) && calc(a) >= c) {
      ;
    } else {
      ++res;
    }
  }
  cout << res << endl;
  return 0;
}
