#include <bits/stdc++.h>
using namespace std;
vector<long long> X;
class union_find {
 public:
  union_find(int n) : par(vector<int>(n, -1)), components(n) {
    W.resize(n);
    for (int i = 0; i < n; ++i) W[i] = X[i];
  }
  bool unite(int x, int y) {
    if ((x = find(x)) == (y = find(y))) {
      return false;
    } else {
      if (par[x] < par[y]) swap(x, y);
      par[y] += par[x];
      par[x] = y;
      W[y] += W[x];
      --components;
      return true;
    }
  }
  int find(int x) {
    if (par[x] < 0)
      return x;
    else
      return par[x] = find(par[x]);
  }
  int size(int x) { return -par[find(x)]; }
  long long weight(int x) { return W[find(x)]; }
  int cnt() { return components; }

 private:
  vector<int> par;
  vector<long long> W;
  int components;
};
struct edge {
  int u;
  int v;
  long long cost;
};
int main() {
  int N, M;
  cin >> N >> M;
  X.resize(N);
  for (int i = 0; i < N; ++i) cin >> X[i];
  vector<edge> G(M);
  vector<vector<pair<int, long long>>> A(N);
  for (int i = 0; i < M; ++i) {
    int a, b;
    long long y;
    cin >> a >> b >> y;
    G[i] = {a - 1, b - 1, y};
    A[a - 1].emplace_back(b - 1, y);
    A[b - 1].emplace_back(a - 1, y);
  }
  auto comp = [](const edge &lhs, const edge &rhs) {
    if (lhs.cost < rhs.cost)
      return true;
    else if (lhs.cost < rhs.cost)
      return false;
    if (lhs.u < rhs.u)
      return true;
    else if (lhs.u > rhs.v)
      return false;
    if (lhs.v < rhs.v)
      return true;
    else
      return false;
  };
  sort(begin(G), end(G), comp);
  vector<bool> candidate(M, false);
  union_find uf(N);
  for (int i = 0; i < M; ++i) {
    uf.unite(G[i].u, G[i].v);
    if (G[i].cost <= uf.weight(G[i].u)) candidate[i] = true;
  }
  set<edge, decltype(comp)> used(comp);
  vector<int> visited(N, false);
  for (int i = M - 1; i >= 0; --i) {
    if (used.count(G[i])) continue;
    if (!candidate[i]) continue;
    queue<int> que;
    que.push(G[i].u);
    long long mc = G[i].cost;
    while (!que.empty()) {
      int v = que.front();
      que.pop();
      if (visited[v]) continue;
      visited[v] = true;
      for (auto to : A[v]) {
        if (!visited[to.first] && to.second <= mc) {
          used.insert({min(v, to.first), max(v, to.first), to.second});
          que.push(to.first);
        }
      }
    }
  }
  cout << M - used.size() << endl;
}
