#include <bits/stdc++.h>
using namespace std;
struct Edge {
  int u;
  int v;
  int w;
  int alive;
  Edge() {
    u = -1;
    v = -1;
    w = -1;
    alive = 0;
  }
  Edge(int u_, int v_, int w_) {
    u = u_;
    v = v_;
    w = w_;
    alive = 1;
  }
  int get(int x) {
    if (x == u) {
      return v;
    } else {
      return u;
    }
  }
  bool operator<(const Edge &other) const { return w < other.w; }
};
struct Dsu {
  int n;
  vector<int> p;
  vector<int> rank;
  Dsu() {}
  Dsu(int n_) {
    n = n_;
    p.resize(n);
    iota(p.begin(), p.end(), 0);
    rank.resize(n);
  }
  int get(int v) {
    if (p[v] != v) {
      p[v] = get(p[v]);
    }
    return p[v];
  }
  int merge(int a, int b) {
    a = get(a);
    b = get(b);
    if (a == b) {
      return 0;
    } else {
      if (rank[a] < rank[b]) {
        swap(a, b);
      }
      p[b] = a;
      if (rank[a] == rank[b]) {
        rank[a]++;
      }
      return 1;
    }
  }
};
const int N = 1e5 + 2;
int a[N];
vector<Edge> E;
set<int> g[N];
int pnt = 1;
int comp[N];
int size_comp[N];
int sum_a_comp[N];
set<pair<Edge, int>> edge_comp[N];
vector<int> seen;
vector<int> seen_e;
int used[N];
int bfs(int st, int lim) {
  queue<int> q;
  q.push(st);
  used[st] = 1;
  seen.push_back(st);
  while (!q.empty()) {
    int v = q.front();
    q.pop();
    for (auto ind : g[v]) {
      Edge e = E[ind];
      int u = e.get(v);
      if (!used[u]) {
        used[u] = 1;
        seen.push_back(u);
        seen_e.push_back(ind);
        q.push(u);
        if ((int)seen.size() > lim) break;
      }
    }
    if ((int)seen.size() > lim) break;
  }
  return q.empty();
}
queue<int> bad_comps;
void split(int ind) {
  Edge e = E[ind];
  g[e.u].erase(ind);
  g[e.v].erase(ind);
  assert(comp[e.u] == comp[e.v]);
  int W = comp[e.u];
  int lim = (size_comp[comp[e.u]] + 1) / 2;
  int fr = e.u;
  seen.clear();
  seen_e.clear();
  if (!bfs(e.u, lim)) {
    fr = e.v;
  }
  for (auto t : seen) {
    used[t] = 0;
  }
  seen.clear();
  seen_e.clear();
  if (false) cerr << "split " << e.u << ' ' << e.v << endl;
  if (false) cerr << fr << ' ' << lim << endl;
  bfs(fr, lim);
  if (false) cerr << "aft " << seen.size() << endl;
  assert((int)seen.size() <= lim);
  for (auto t : seen) {
    used[t] = 0;
  }
  for (auto t : seen) {
    size_comp[comp[t]]--;
    sum_a_comp[comp[t]] -= a[t];
    comp[t] = pnt;
    size_comp[comp[t]]++;
    sum_a_comp[comp[t]] += a[t];
  }
  for (auto t : seen_e) {
    edge_comp[W].erase({E[t], t});
    edge_comp[pnt].insert({E[t], t});
  }
  edge_comp[W].erase({E[ind], ind});
  if (!edge_comp[W].empty() && sum_a_comp[W] < edge_comp[W].rbegin()->first.w) {
    bad_comps.push(W);
  }
  if (!edge_comp[pnt].empty() &&
      sum_a_comp[pnt] < edge_comp[pnt].rbegin()->first.w) {
    bad_comps.push(pnt);
  }
  pnt++;
}
signed main() {
  ios_base::sync_with_stdio(false);
  cin.tie(0);
  int n, m;
  cin >> n >> m;
  for (int i = 0; i < n; i++) {
    cin >> a[i];
  }
  for (int i = 0; i < m; i++) {
    int u, v, w;
    cin >> u >> v >> w;
    u--;
    v--;
    E.push_back(Edge({u, v, w}));
  }
  sort(E.begin(), E.end());
  Dsu D(n);
  for (int i = 0; i < m; i++) {
    if (D.merge(E[i].u, E[i].v)) {
      if (false) cerr << "E! " << E[i].u << ' ' << E[i].v << endl;
      edge_comp[0].insert({E[i], i});
      g[E[i].v].insert(i);
      g[E[i].u].insert(i);
    }
  }
  size_comp[0] = n;
  for (int i = 0; i < n; i++) {
    sum_a_comp[0] += a[i];
  }
  if (!edge_comp[0].empty() && sum_a_comp[0] < edge_comp[0].rbegin()->first.w) {
    bad_comps.push(0);
  }
  while (!bad_comps.empty()) {
    int v = bad_comps.front();
    bad_comps.pop();
    split(edge_comp[v].rbegin()->second);
  }
  for (int i = 0; i < n; i++) {
    if (false) cerr << comp[i] << ' ';
  }
  if (false) cerr << endl;
  int ans = 0;
  for (auto t : E) {
    if (comp[t.u] == comp[t.v] && sum_a_comp[comp[t.u]] >= t.w) ans++;
  }
  cout << m - ans << '\n';
}
