#include <bits/stdc++.h>
template <typename T>
void MACRO_VAR_Scan(T& t) {
  std::cin >> t;
}
template <typename First, typename... Rest>
void MACRO_VAR_Scan(First& first, Rest&... rest) {
  std::cin >> first;
  MACRO_VAR_Scan(rest...);
}
template <typename T>
void MACRO_VEC_ROW_Init(int n, T& t) {
  t.resize(n);
}
template <typename First, typename... Rest>
void MACRO_VEC_ROW_Init(int n, First& first, Rest&... rest) {
  first.resize(n);
  MACRO_VEC_ROW_Init(n, rest...);
}
template <typename T>
void MACRO_VEC_ROW_Scan(int p, T& t) {
  std::cin >> t[p];
}
template <typename First, typename... Rest>
void MACRO_VEC_ROW_Scan(int p, First& first, Rest&... rest) {
  std::cin >> first[p];
  MACRO_VEC_ROW_Scan(p, rest...);
}
template <class T>
inline T CHMAX(T& a, const T b) {
  return a = (a < b) ? b : a;
}
template <class T>
inline T CHMIN(T& a, const T b) {
  return a = (a > b) ? b : a;
}
template <class T>
using V = std::vector<T>;
template <class T>
using VV = V<V<T>>;
template <typename S, typename T>
std::ostream& operator<<(std::ostream& os, std::pair<S, T> p) {
  os << "(" << p.first << ", " << p.second << ")";
  return os;
}
using ll = long long;
using ull = unsigned long long;
using ld = long double;
using PAIR = std::pair<ll, ll>;
using PAIRLL = std::pair<ll, ll>;
constexpr ll INFINT = 1 << 30;
constexpr ll INFINT_LIM = (1LL << 31) - 1;
constexpr ll INFLL = 1LL << 60;
constexpr ll INFLL_LIM = (1LL << 62) - 1 + (1LL << 62);
constexpr double EPS = 1e-6;
constexpr ll MOD = 1000000007;
constexpr double PI = 3.141592653589793238462643383279;
template <class T, size_t N>
void FILL(T (&a)[N], const T& val) {
  for (auto& x : a) x = val;
}
template <class ARY, size_t N, size_t M, class T>
void FILL(ARY (&a)[N][M], const T& val) {
  for (auto& b : a) FILL(b, val);
}
template <class T>
void FILL(std::vector<T>& a, const T& val) {
  for (auto& x : a) x = val;
}
template <class ARY, class T>
void FILL(std::vector<std::vector<ARY>>& a, const T& val) {
  for (auto& b : a) FILL(b, val);
}
class UnionFind {
 private:
  std::vector<ll> parent;
  std::vector<ll> height;
  std::vector<ll> m_size;

 public:
  UnionFind(ll size_) : parent(size_), height(size_, 0), m_size(size_, 1) {
    for (ll i = 0; i < size_; ++i) parent[i] = i;
  }
  void init(ll size_) {
    parent.resize(size_);
    height.resize(size_, 0);
    m_size.resize(size_, 0);
    for (ll i = 0; i < size_; ++i) parent[i] = i;
  }
  ll find(ll x) {
    if (parent[x] == x) return x;
    return parent[x] = find(parent[x]);
  }
  void unite(ll x, ll y) {
    x = find(x);
    y = find(y);
    if (x == y) return;
    ll t = size(x) + size(y);
    m_size[x] = m_size[y] = t;
    if (height[x] < height[y])
      parent[x] = y;
    else
      parent[y] = x;
    if (height[x] == height[y]) ++height[x];
  }
  bool same(ll x, ll y) { return find(x) == find(y); }
  ll size(ll x) {
    if (parent[x] == x) return m_size[x];
    return size(parent[x] = find(parent[x]));
  }
};
signed main() {
  std::ios::sync_with_stdio(false);
  std::cin.tie(0);
  ;
  ll n, m;
  MACRO_VAR_Scan(n, m);
  ;
  std::vector<ll> x(n);
  for (auto& i : x) std::cin >> i;
  ;
  std::vector<ll> a, b, y;
  MACRO_VEC_ROW_Init(m, a, b, y);
  for (ll w_ = 0; w_ < m; ++w_) {
    MACRO_VEC_ROW_Scan(w_, a, b, y);
  };
  {
    struct S {
      ll a, b, y;
    };
    V<S> s(m);
    for (ll i = 0; i < ll(m); ++i) s[i] = S{a[i], b[i], y[i]};
    std::sort((s).begin(), (s).end(), [&](S& l, S& r) { return l.y < r.y; });
    for (ll i = 0; i < ll(m); ++i) {
      a[i] = --s[i].a;
      b[i] = --s[i].b;
      y[i] = s[i].y;
    }
  }
  ll ok = -1;
  {
    UnionFind uf(n);
    V<ll> cost(n, 0);
    for (ll i = 0; i < ll(n); ++i) cost[i] = x[i];
    V<ll> max(n, -INFINT);
    std::set<ll> ngset;
    for (ll i = 0; i < ll(m); ++i) {
      if (!uf.same(a[i], b[i])) {
        ll fa = uf.find(a[i]);
        ll fb = uf.find(b[i]);
        ngset.erase(fa);
        ngset.erase(fb);
        ll c = cost[fa] + cost[fb];
        ll ma = std::max({max[fa], max[fb], y[i]});
        uf.unite(a[i], b[i]);
        ll newfa = uf.find(a[i]);
        cost[fa] = cost[fb] = c;
        max[fa] = max[fb] = ma;
        if (ma > c) ngset.insert(newfa);
      }
      if (ngset.empty()) ok = i;
    }
  }
  UnionFind uf(n);
  V<ll> cost(n, 0);
  for (ll i = 0; i < ll(n); ++i) cost[i] = x[i];
  V<ll> max(n, -INFINT);
  V<bool> used(m, false);
  for (ll i = 0; i < ll(ok + 1); ++i) {
    if (!uf.same(a[i], b[i])) {
      ll fa = uf.find(a[i]);
      ll fb = uf.find(b[i]);
      ll c = cost[fa] + cost[fb];
      ll ma = std::max({max[fa], max[fb], y[i]});
      uf.unite(a[i], b[i]);
      ll newfa = uf.find(a[i]);
      cost[fa] = cost[fb] = c;
      max[fa] = max[fb] = ma;
    }
  }
  for (ll i = 0; i < ll(m); ++i) {
    if (uf.same(a[i], b[i])) {
      ll fa = uf.find(a[i]);
      if (y[i] <= cost[fa]) {
        used[i] = true;
      }
    }
  }
  ll ans = m;
  for (ll i = 0; i < ll(m); ++i) ans -= used[i];
  std::cout << (ans);
  std::cout << "\n";
  ;
  return 0;
}
