#include <bits/stdc++.h>
using namespace std;
class UnionFindTree {
 private:
  int n;
  int groupNum;
  vector<int> parent;
  vector<int> rank;
  vector<int> num;
  vector<pair<int, int> > val;
  int find(int i) {
    if (parent[i] == i)
      return i;
    else
      return parent[i] = find(parent[i]);
  }

 public:
  UnionFindTree(int n) {
    this->n = n;
    groupNum = n;
    parent.resize(n);
    for (int i = 0; i < n; ++i) parent[i] = i;
    rank.assign(n, 0);
    num.assign(n, 1);
    val.assign(n, make_pair(0, 0));
  }
  void unite(int a, int b) {
    if ((a = find(a)) != (b = find(b))) {
      if (rank[a] < rank[b]) {
        parent[a] = b;
        num[b] += num[a];
        val[b].first += val[a].first;
        val[b].second += val[a].second;
      } else {
        parent[b] = a;
        if (rank[a] == rank[b]) ++rank[a];
        num[a] += num[b];
        val[a].first += val[b].first;
        val[a].second += val[b].second;
      }
      --groupNum;
    }
  }
  bool same(int a, int b) { return find(a) == find(b); }
  int getNum() { return groupNum; }
  int getNum(int a) { return num[find(a)]; }
  pair<int, int>& getVal(int a) { return val[find(a)]; }
};
class Edge {
 public:
  int a, b, weight;
  Edge() {}
  bool operator<(const Edge& other) const { return weight < other.weight; }
};
int main() {
  int n, m;
  cin >> n >> m;
  vector<int> x(n);
  for (int i = 0; i < n; ++i) cin >> x[i];
  vector<Edge> edges(m);
  for (int i = 0; i < m; ++i) {
    cin >> edges[i].a >> edges[i].b >> edges[i].weight;
    --edges[i].a;
    --edges[i].b;
  }
  sort(edges.begin(), edges.end());
  UnionFindTree uft(n);
  for (int i = 0; i < n; ++i) uft.getVal(i) = make_pair(x[i], 0);
  int ans = m;
  for (int i = 0; i < m; ++i) {
    int a = edges[i].a;
    int b = edges[i].b;
    uft.unite(a, b);
    if (edges[i].weight <= uft.getVal(a).first) {
      ans -= uft.getVal(a).second + 1;
      uft.getVal(a).second = 0;
    } else {
      ++uft.getVal(a).second;
    }
  }
  cout << ans << endl;
  return 0;
}
