#include <bits/stdc++.h>
using namespace std;
const int MAX_N = 1e5, MAX_M = 1e5;
int N, M;
long long X[MAX_N];
struct edge {
  int s, t;
  long long cst;
  int inx;
  edge(int s = -1, int t = -1, long long c = 0, int i = -1)
      : s(s), t(t), cst(c), inx(i) {}
  bool operator<(const edge &e) const { return cst < e.cst; }
};
struct edge2 {
  int to;
  long long cst;
  int inx;
  edge2(int t = -1, long long c = 0, int i = -1) : to(t), cst(c), inx(i) {}
};
edge E[MAX_M];
vector<edge2> G[MAX_N];
int used[MAX_M];
bool koho[MAX_M];
bool visit[MAX_N];
int par[MAX_N];
long long sm[MAX_N];
int fndpar(int v) {
  if (par[v] == v) {
    return v;
  }
  return par[v] = fndpar(par[v]);
}
void unite(int s, int t) {
  s = fndpar(s);
  t = fndpar(t);
  par[t] = s;
  sm[s] += sm[t];
}
void dfs(int v, long long c) {
  visit[v] = true;
  for (auto e : G[v]) {
    if (e.cst <= c && !visit[e.to] && used[e.inx] != 0) {
      used[e.inx] = 1;
      dfs(e.to, c);
    }
  }
}
int main() {
  cin >> N >> M;
  for (int i = (0); i < (N); i++) cin >> X[i];
  for (int i = (0); i < (M); i++) {
    int a, b;
    long long y;
    cin >> a >> b >> y;
    a--;
    b--;
    E[i] = edge(a, b, y, i);
    G[a].push_back(edge2(b, y, i));
    G[b].push_back(edge2(a, y, i));
  }
  sort(E, E + M);
  for (int i = (0); i < (N); i++) {
    par[i] = i;
    sm[i] = X[i];
  }
  for (int i = (0); i < (M); i++) {
    auto e = E[i];
    if (fndpar(e.s) != fndpar(e.t)) {
      unite(e.s, e.t);
    }
    if (sm[fndpar(e.s)] >= e.cst) {
      koho[e.inx] = true;
    }
  }
  reverse(E, E + M);
  int ans = 0;
  memset(used, -1, sizeof(used));
  for (int i = (0); i < (M); i++) {
    auto e = E[i];
    if (used[e.inx] != -1) continue;
    if (koho[e.inx]) {
      dfs(e.s, e.cst);
    } else {
      used[e.inx] = 0;
      ans++;
    }
  }
  cout << ans << endl;
}
