#include <bits/stdc++.h>
using namespace std;
struct PartiallyPersistentUnionFind {
  vector<int> data;
  vector<int> last;
  vector<long long> cost;
  vector<vector<pair<int, int> > > add;
  vector<vector<pair<int, long long> > > add2;
  PartiallyPersistentUnionFind() {}
  PartiallyPersistentUnionFind(int sz, vector<long long> costs)
      : cost(sz, -1), data(sz, -1), last(sz, 1e9), add(sz), add2(sz) {
    for (auto &vs : add) vs.emplace_back(-1, -1);
    for (auto &vs : add2) vs.emplace_back(-1, (long long)-1);
    for (int i = 0; i < costs.size(); i++) {
      cost[i + 1] = -costs[i];
    }
  }
  bool merge(int t, int x, int y) {
    x = root(t, x);
    y = root(t, y);
    if (x == y) return false;
    if (data[x] > data[y]) swap(x, y);
    data[x] += data[y];
    cost[x] += cost[y];
    add[x].emplace_back(t, data[x]);
    add2[x].emplace_back(t, cost[x]);
    data[y] = x;
    cost[y] = x;
    last[y] = t;
    return true;
  }
  int root(int t, int x) {
    if (t < last[x]) return x;
    return root(t, data[x]);
  }
  int size(int t, int x) {
    x = root(t, x);
    return -prev(lower_bound(begin(add[x]), end(add[x]), make_pair(t, 0)))
                ->second;
  }
  int Cost(int t, int x) {
    x = root(t, x);
    return -prev(lower_bound(begin(add2[x]), end(add2[x]),
                             make_pair(t, (long long)0)))
                ->second;
  }
  bool issame(int t, int x, int y) { return root(t, x) == root(t, y); }
};
bool checked[100005];
vector<pair<int, int> > pathes[100005];
void bfs(int from, int time) {
  if (checked[from]) return;
  checked[from] = true;
  for (int i = 0; i < pathes[from].size(); i++) {
    if (time < pathes[from][i].second) return;
    int to = pathes[from][i].first;
    bfs(to, time);
  }
}
int main() {
  long long N, M;
  cin >> N >> M;
  vector<long long> X;
  for (int i = 0; i < N; i++) {
    long long in;
    cin >> in;
    X.push_back(in);
  }
  PartiallyPersistentUnionFind uni(100050, X);
  vector<pair<long long, pair<int, int> > > edges;
  for (int i = 1; i <= M; i++) {
    int a, b;
    long long y;
    cin >> a >> b >> y;
    edges.push_back({y, {a, b}});
  }
  sort(edges.begin(), edges.end());
  for (int i = 0; i < M; i++) {
    uni.merge(i, edges[i].second.first, edges[i].second.second);
    int a = edges[i].second.first;
    int b = edges[i].second.second;
    pathes[a].push_back({b, i});
    pathes[b].push_back({a, i});
  }
  int ans = 0;
  for (int i = M - 1; i >= 0; i--) {
    int now = edges[i].second.first;
    if (checked[now]) continue;
    long long limit = edges[i].first;
    if (uni.Cost(i, now) < limit) {
      ans++;
      continue;
    }
    bfs(now, i);
  }
  cout << ans << endl;
  return 0;
}
