#include <bits/stdc++.h>
using namespace std;
const int MAX_N = 100005;
class UF {
 private:
  int sz;
  vector<int> par, nrank;

 public:
  vector<long long> weight;
  UF() {}
  UF(int node_size) {
    sz = node_size;
    par.resize(sz), nrank.resize(sz, 0);
    weight.resize(sz, 0);
    for (int i = 0; i < (int)(sz); ++i) par[i] = i;
  }
  int find(int x) {
    if (par[x] == x) {
      return x;
    } else {
      return par[x] = find(par[x]);
    }
  }
  void unite(int x, int y) {
    x = find(x), y = find(y);
    if (x == y) return;
    if (nrank[x] < nrank[y]) swap(x, y);
    weight[x] += weight[y];
    par[y] = x;
    if (nrank[x] == nrank[y]) nrank[x]++;
  }
  bool same(int x, int y) { return find(x) == find(y); }
};
struct edge {
  int from, to;
  long long cost;
  bool operator<(const edge& another) const { return cost < another.cost; };
};
vector<int> G[MAX_N];
bool used[2 * MAX_N];
int ver[2 * MAX_N];
int ans = 0;
void dfs(int u) {
  ans++;
  for (auto&(v) : (G[u])) {
    if (!used[v]) {
      dfs(v);
    }
  }
}
int main() {
  cin.tie(0);
  ios::sync_with_stdio(false);
  int n, m;
  cin >> n >> m;
  UF uf(n);
  for (int i = 0; i < (int)(n); ++i) {
    cin >> uf.weight[i];
  }
  vector<edge> vec(m);
  for (int i = 0; i < (int)(m); ++i) {
    int a, b, y;
    cin >> a >> b >> y;
    vec[i] = (edge){a - 1, b - 1, y};
  }
  sort((vec).begin(), (vec).end());
  for (int i = 0; i < (int)(n); ++i) {
    ver[i] = i;
    used[i] = true;
  }
  int id = n;
  for (auto&(e) : (vec)) {
    int p = uf.find(e.from), q = uf.find(e.to);
    int u = ver[p], v = ver[q];
    if (p != q) {
      if (e.cost <= uf.weight[p] + uf.weight[q]) {
        used[id] = true;
      }
      uf.unite(e.from, e.to);
      G[id].push_back(u), G[id].push_back(v);
    } else {
      G[id].push_back(u);
      if (e.cost <= uf.weight[p]) {
        used[id] = true;
      }
    }
    ver[uf.find(e.from)] = id++;
  }
  dfs(id - 1);
  cout << ans << "\n";
  return 0;
}
