#include <bits/stdc++.h>
using namespace std;
template <typename T>
bool setmin(T& a, T b) {
  if (b < a) {
    a = b;
    return true;
  } else {
    return false;
  }
}
template <typename T>
bool setmax(T& a, T b) {
  if (b > a) {
    a = b;
    return true;
  } else {
    return false;
  }
}
template <typename T>
bool setmineq(T& a, T b) {
  if (b <= a) {
    a = b;
    return true;
  } else {
    return false;
  }
}
template <typename T>
bool setmaxeq(T& a, T b) {
  if (b >= a) {
    a = b;
    return true;
  } else {
    return false;
  }
}
long long signed int mo(long long signed int a, long long signed int b) {
  assert(b > 0);
  a %= b;
  if (a < 0) {
    a += b;
  }
  return a;
}
long long signed int fl(long long signed int a, long long signed int b) {
  assert(b > 0);
  return (a > 0 ? a / b : (a - b + 1) / b);
}
long long signed int ce(long long signed int a, long long signed int b) {
  assert(b > 0);
  return (a < 0 ? a / b : (a + b - 1) / b);
}
class UnionFind {
 private:
  int n, s;
  vector<int> p_id;
  vector<vector<int>> v;

 public:
  UnionFind(int n = 0) { init(n); }
  void init(int arg_n) {
    n = s = arg_n;
    p_id.clear();
    v.clear();
    for (int i = (0); i < (n); ++i) {
      p_id.push_back(i);
      v.emplace_back(1, i);
    }
  }
  int id(int i) { return p_id.at(i); }
  bool unite(int x, int y) {
    x = id(x);
    y = id(y);
    if (x == y) {
      return false;
    }
    if (v[x].size() < v[y].size()) {
      swap(x, y);
    }
    for (auto& e : v[y]) {
      v[x].push_back(e);
      p_id[e] = x;
    }
    v[y].clear();
    s--;
    return true;
  }
  const vector<int>& operator[](int i) { return v[id(i)]; }
  int size() { return s; }
  int get_n() const { return n; }
  const vector<vector<int>>& get_v() const { return v; }
};
ostream& operator<<(ostream& os, const UnionFind& uf) {
  for (int i = (0); i < (uf.get_n()); ++i) {
    os << i << ": ";
    for (auto& e : uf.get_v()[i]) {
      os << e << " ";
    }
    os << "\n";
  }
  return os;
}
const int M = 100000;
long long signed int n, m, x[M];
array<long long signed int, 3> yab[M];
bool mst[M];
long long signed int id[M], d[M], c[M];
vector<int> g[M], r, w;
void dfs(int v, int p, int dd) {
  d[v] = dd;
  c[v] = 1;
  for (auto& e : g[v]) {
    if (e == p) {
      continue;
    }
    dfs(e, v, dd + 1);
    c[v] += c[e];
  }
}
void del_2(int L, int S, int v, int p) {
  id[v] = S;
  w[L] -= x[v];
  w[S] += x[v];
  for (auto& e : g[v]) {
    if (e == p) {
      continue;
    }
    del_2(L, S, e, v);
  }
}
void del(int rl, int rs, int v, int p) {
  int L = id[v];
  int S = static_cast<int>(r.size());
  r.push_back(-1);
  w.push_back(0);
  r[L] = rl;
  r[S] = rs;
  del_2(L, S, v, p);
}
int main() {
  cin >> n >> m;
  for (int i = (0); i < (n); ++i) {
    cin >> x[i];
  }
  for (int i = (0); i < (m); ++i) {
    long long signed int a, b, y;
    cin >> a >> b >> y;
    a--;
    b--;
    yab[i] = {y, a, b};
  }
  sort(yab, yab + m);
  UnionFind uf(n);
  for (int i = (0); i < (m); ++i) {
    int a = yab[i][1];
    int b = yab[i][2];
    if (uf.unite(a, b)) {
      mst[i] = true;
      g[a].push_back(b);
      g[b].push_back(a);
    }
  }
  dfs(0, -1, 0);
  r.push_back(0);
  w.push_back(0);
  for (int i = (0); i < (n); ++i) {
    w[0] += x[i];
  }
  int ans = 0;
  for (int i = (m)-1; i >= (0); --i) {
    long long signed int y = yab[i][0];
    long long signed int a = yab[i][1];
    long long signed int b = yab[i][2];
    if (w[id[a]] >= y) {
      continue;
    }
    if (mst[i]) {
      if (d[a] < d[b]) {
        swap(a, b);
      }
      int R = r[id[a]];
      if (c[a] < c[R] - c[a]) {
        del(R, a, a, b);
      } else {
        del(a, R, b, a);
      }
    }
    ans++;
  }
  cout << ans << endl;
  return 0;
}
