#include <bits/stdc++.h>
using namespace std;
struct Edge {
  int a, b, y;
};
struct Merge {
  Edge e;
  int za, zb, l;
};
bool operator<(const Edge& e1, const Edge& e2) {
  if (e1.y != e2.y) return e1.y < e2.y;
  if (e1.a != e2.a) return e1.a < e2.a;
  if (e1.b != e2.b) return e1.b < e2.b;
  return false;
}
class UnionFind {
 public:
  explicit UnionFind(int n) : data_(n, -1) {}
  int root(int i) { return (data_[i] >= 0) ? (data_[i] = root(data_[i])) : i; }
  bool unify(int i, int j) {
    i = root(i);
    j = root(j);
    if (i == j) return false;
    if (-data_[i] >= -data_[j]) {
      data_[i] += data_[j];
      data_[j] = i;
    } else {
      data_[j] += data_[i];
      data_[i] = j;
    }
    return true;
  }

 private:
  vector<int> data_;
};
int main() {
  int n, m;
  scanf("%d%d", &n, &m);
  vector<int> x(n);
  for (int i = 0; i < n; i++) scanf("%d", &x[i]);
  vector<Edge> e(m);
  for (int i = 0; i < m; i++) {
    scanf("%d%d%d", &e[i].a, &e[i].b, &e[i].y);
    --e[i].a;
    --e[i].b;
  }
  sort(e.begin(), e.end());
  vector<int> z = x;
  UnionFind uf(n);
  vector<Merge> merges;
  vector<int> last(n, -1);
  for (int i = 0; i < m; i++) {
    int a = uf.root(e[i].a);
    int b = uf.root(e[i].b);
    if (uf.unify(a, b)) {
      if (last[a] >= 0) merges[last[a]].l = merges.size();
      if (last[b] >= 0) merges[last[b]].l = merges.size();
      last[uf.root(a)] = merges.size();
      merges.push_back({e[i], z[a], z[b], -1});
      z[uf.root(a)] = z[a] + z[b];
    }
  }
  for (int i = merges.size() - 1; i >= 0; i--) {
    auto& mg = merges[i];
    if (mg.l >= 0 && merges[mg.l].za > 0) continue;
    if (mg.e.y <= mg.za + mg.zb) continue;
    mg.za = mg.zb = 0;
  }
  UnionFind uf2(n);
  for (auto& mg : merges) {
    if (mg.za > 0) {
      uf2.unify(mg.e.a, mg.e.b);
    }
  }
  vector<int> w(n, 0);
  for (int i = 0; i < n; i++) w[uf2.root(i)] += x[i];
  int ans = 0;
  for (int i = 0; i < m; i++)
    if (e[i].y > w[uf2.root(e[i].a)]) ++ans;
  printf("%d\n", ans);
  return 0;
}
