#include <bits/stdc++.h>
using namespace std;
long long N, M, H, W, K, Q, A, B;
string S, T;
const long long MOD = (1e+9) + 7;
const long long INF = 1LL << 60;
struct edge {
  int a, b, c;
  edge() {}
  edge(int _a, int _b, int _c) {
    a = _a;
    b = _b;
    c = _c;
  }
};
int main() {
  class union_find {
    vector<long> parent, tree_size, tree_cost;

   public:
    union_find(unsigned long _n) : parent(_n), tree_size(_n, 1), tree_cost(_n) {
      for (unsigned long i = 0; i < _n; ++i) parent[i] = i;
    }
    void init(vector<long long> &cost) {
      for (int i = 0; i < cost.size(); ++i) tree_cost[i] = cost[i];
    }
    long long find(long long x) {
      while (parent[x] != x) x = parent[x] = parent[parent[x]];
      return x;
    }
    void merge(long long a, long long b) {
      a = find(a);
      b = find(b);
      if (a == b) return;
      if (tree_size[a] < tree_size[b]) swap(a, b);
      tree_size[a] += tree_size[b];
      tree_cost[a] += tree_cost[b];
      parent[b] = a;
      return;
    }
    bool same(long long a, long long b) {
      a = find(a);
      b = find(b);
      return a == b;
    }
    long long get_cost(int a) { return tree_cost[find(a)]; }
  };
  cin >> N >> M;
  vector<long long> x(N), ord(M);
  for (int i = 0; i < N; i++) cin >> x[i];
  vector<edge> e(0);
  for (int i = 0; i < M; i++) {
    cin >> A >> B >> K;
    --A;
    --B;
    e.emplace_back(A, B, K);
    ord[i] = i;
  }
  sort(ord.begin(), ord.end(), [&](int x, int y) { return e[x].c < e[y].c; });
  union_find uf(N + 10);
  uf.init(x);
  int max_cost = 0;
  set<int> bad;
  for (int i = 0; i < M; i++) {
    int id = ord[i];
    int a = uf.find(e[id].a), b = uf.find(e[id].b);
    bad.erase(a);
    bad.erase(b);
    uf.merge(a, b);
    if (uf.get_cost(a) < e[id].c) bad.insert(uf.find(a));
    if (bad.empty()) max_cost = e[id].c;
  }
  int ans = 0;
  for (int i = 0; i < M; i++) ans += e[i].c > max_cost;
  cout << ans << endl;
}
