#include <bits/stdc++.h>
using namespace std;
const long long INF = 1e9 * 1e9, SIZE = 1e5 + 10;
vector<long long> vec;
vector<tuple<long long, long long, long long>> edges, good;
vector<set<long long>> gr;
long long dsu[SIZE], siz[SIZE];
vector<pair<long long, long long>> upds;
long long find(int v) {
  if (dsu[v] == v) return v;
  return find(dsu[v]);
}
void uni(int v, int u) {
  v = find(v);
  u = find(u);
  if (u == v) {
    return;
  }
  if (u != v) {
    if (siz[u] < siz[v]) {
      dsu[u] = v;
    } else {
      dsu[v] = u;
    }
  }
}
long long cnt = 1, used[SIZE];
long long dfs(int v) {
  used[v] = cnt;
  long long vl = vec[v];
  for (auto to : gr[v]) {
    if (used[to] != cnt) vl += dfs(to);
  }
  return vl;
}
int main() {
  cin.tie(0);
  cout.tie(0);
  ios_base::sync_with_stdio(0);
  ;
  long long n, m;
  cin >> n >> m;
  vec.resize(n);
  for (int i = 0; i < n; i++) cin >> vec[i];
  for (int i = 0; i < m; i++) {
    long long u, v, c;
    cin >> u >> v >> c;
    u--;
    v--;
    edges.push_back({c, u, v});
  }
  sort(edges.begin(), edges.end());
  gr.resize(n);
  for (int i = 0; i < n; i++) {
    dsu[i] = i;
    siz[i] = 1;
  }
  for (int i = 0; i < edges.size(); i++) {
    long long u = get<1>(edges[i]), v = get<2>(edges[i]);
    if (find(u) != find(v)) {
      uni(u, v);
      good.push_back(edges[i]);
      gr[u].insert(v);
      gr[v].insert(u);
    }
  }
  reverse(good.begin(), good.end());
  for (int i = 0; i < good.size(); i++) {
    cnt++;
    long long u = get<1>(good[i]), v = get<2>(good[i]);
    long long cn = dfs(u);
    if (cn < get<0>(good[i])) {
      gr[u].erase(v);
      gr[v].erase(u);
    }
  }
  for (int i = 0; i < n; i++) {
    for (auto cur : gr[i]) uni(i, cur);
  }
  long long c = 0;
  for (auto cur : edges) {
    if (find(get<1>(cur)) == find(get<2>(cur))) {
      cnt++;
      long long rc = dfs(get<1>(cur));
      if (rc < get<0>(cur)) c++;
    }
  }
  cout << c;
  return 0;
}
