#include <bits/stdc++.h>
using namespace std;
using ll = long long;
struct UnionFind {
  std::vector<int> data;
  std::vector<ll> w, max_w;
  UnionFind() {}
  UnionFind(int size) : data(size, -1), w(size), max_w(size, -1) {}
  bool unite(int x, int y) {
    x = root(x);
    y = root(y);
    if (x != y) {
      if (data[y] < data[x]) std::swap(x, y);
      data[x] += data[y];
      data[y] = x;
      w[x] += w[y];
      max_w[x] = max(max_w[x], max_w[y]);
    } else
      max_w[x] = max(max_w[x], max_w[y]);
    return x != y;
  }
  bool find(int x, int y) { return root(x) == root(y); }
  int size(int x) { return -data[root(x)]; }
  int root(int x) { return data[x] < 0 ? x : data[x] = root(data[x]); }
};
struct Edge {
  int u, v, w;
  Edge() {}
  Edge(int _u, int _v, int _w) : u(_u), v(_v), w(_w) {}
};
bool operator<(const Edge &e1, const Edge &e2) { return e1.w < e2.w; }
int main() {
  cin.tie(0);
  ios::sync_with_stdio(false);
  int n, m;
  cin >> n >> m;
  vector<int> x(n);
  for (auto &&xx : x) cin >> xx;
  vector<Edge> edges(m);
  for (int i = 0; i < m; ++i) {
    cin >> edges[i].u >> edges[i].v >> edges[i].w;
    --edges[i].u;
    --edges[i].v;
  }
  sort(edges.begin(), edges.end());
  UnionFind uf(n);
  for (int i = 0; i < n; ++i) uf.w[i] = x[i];
  for (const auto &e : edges) {
    uf.unite(e.u, e.v);
    if (e.w <= uf.w[uf.root(e.u)]) uf.max_w[uf.root(e.u)] = e.w;
    uf.unite(e.u, e.v);
  }
  int res = 0;
  for (const auto &e : edges) {
    if (uf.max_w[uf.root(e.u)] < e.w) ++res;
  }
  cout << res << endl;
  return 0;
}
