#include <bits/stdc++.h>
using namespace std;
constexpr int INF = numeric_limits<int>::max() / 2;
constexpr long long LINF = numeric_limits<long long>::max() / 3;
struct Double {
  double d;
  explicit Double(double x) : d(x) {}
};
ostream& operator<<(ostream& os, const Double x) {
  os << fixed << setprecision(20) << x.d;
  return os;
}
template <typename T>
ostream& operator<<(ostream& os, const vector<T>& vec) {
  os << "[";
  for (const auto& v : vec) {
    os << v << ",";
  }
  os << "]";
  return os;
}
template <typename T, typename U>
ostream& operator<<(ostream& os, const pair<T, U>& p) {
  os << "(" << p.first << "," << p.second << ")";
  return os;
}
template <typename T>
ostream& operator<<(ostream& os, const set<T>& st) {
  os << "{";
  for (T v : st) os << v << ",";
  os << "}";
  return os;
}
template <typename T, typename U>
inline void chmax(T& x, U y) {
  if (y > x) x = y;
}
template <typename T, typename U>
inline void chmin(T& x, U y) {
  if (y < x) x = y;
}
constexpr double eps = 1e-10;
const int dx[] = {1, 0, -1, 0}, dy[] = {0, 1, 0, -1};
using ll = __int128;
ll n, m;
vector<ll> X;
struct edge {
  int u, v;
  ll cost;
  edge() {}
  edge(int u_, int v_, ll cost_) : u(u_), v(v_), cost(cost_) {}
  bool operator<(const edge& e) const { return cost < e.cost; }
};
vector<edge> es;
struct UnionFind {
  vector<int> rank, parent;
  vector<ll> cost;
  UnionFind() {}
  UnionFind(int n) {
    rank.resize(n, 0);
    parent.resize(n, 0);
    cost.resize(n, 0);
    for (int i = 0; i < n; i++) {
      parent[i] = i;
      rank[i] = 0;
      cost[i] = X[i];
    }
  }
  int find(int x) {
    if (parent[x] == x)
      return x;
    else
      return parent[x] = find(parent[x]);
  }
  void unite(int x, int y) {
    x = find(x);
    y = find(y);
    if (x == y) return;
    if (rank[x] < rank[y]) {
      parent[x] = y;
      cost[y] += cost[x];
      cost[x] = 0;
    } else {
      parent[y] = x;
      cost[x] += cost[y];
      cost[y] = 0;
    }
  }
  bool same(int x, int y) { return find(x) == find(y); }
  ll sum(int x) { return cost[find(x)]; }
};
int main() {
  long long nn, mm;
  cin >> nn >> mm;
  n = nn;
  m = mm;
  X.resize(n);
  es.resize(m);
  for (int i = 0; i < (int)(n); i++) {
    long long x;
    cin >> x;
    X[i] = x;
  }
  for (int i = 0; i < (int)(m); i++) {
    int a, b;
    long long y;
    cin >> a >> b >> y;
    a--;
    b--;
    es[i] = edge(a, b, y);
  }
  sort((es).begin(), (es).end());
  reverse((es).begin(), (es).end());
  int l, r;
  l = 0;
  r = m;
  while (r - l > 1) {
    int mid = (l + r) / 2;
    UnionFind uf(n);
    for (int i = mid; i < m; i++) {
      uf.unite(es[i].u, es[i].v);
    }
    bool ok = true;
    for (int i = mid; i < m; i++) {
      ll c = uf.sum(es[i].u);
      if (c < es[i].cost) {
        ok = false;
        break;
      }
    }
    if (ok) {
      r = mid;
    } else {
      l = mid;
    }
  }
  cout << r << endl;
}
