#include <bits/stdc++.h>
using namespace std;
using namespace placeholders;
using LL = long long;
using ULL = unsigned long long;
using VI = vector<int>;
using VVI = vector<vector<int> >;
using VS = vector<string>;
using ISS = istringstream;
using OSS = ostringstream;
using PII = pair<int, int>;
using VPII = vector<pair<int, int> >;
template <typename T = int>
using VT = vector<T>;
template <typename T = int>
using VVT = vector<vector<T> >;
template <typename T = int>
using LIM = numeric_limits<T>;
template <typename T>
inline istream &operator>>(istream &s, vector<T> &v) {
  for (T &t : v) {
    s >> t;
  }
  return s;
}
template <typename T>
inline ostream &operator<<(ostream &s, const vector<T> &v) {
  for (int i = 0; i < int(v.size()); ++i) {
    s << (" " + !i) << v[i];
  }
  return s;
}
void in_impl(){};
template <typename T, typename... TS>
void in_impl(T &head, TS &...tail) {
  cin >> head;
  in_impl(tail...);
}
template <typename T>
struct getv_fmt;
template <>
struct getv_fmt<int> {
  static constexpr const char *fmt = "%d";
};
template <>
struct getv_fmt<long long> {
  static constexpr const char *fmt = "%lld";
};
template <typename T>
void getv(std::vector<T> &v) {
  for_each(begin(v), end(v), [](T &a) { scanf(getv_fmt<T>::fmt, &a); });
};
template <typename T>
inline T fromString(const string &s) {
  T res;
  istringstream iss(s);
  iss >> res;
  return res;
}
template <typename T>
inline string toString(const T &a) {
  ostringstream oss;
  oss << a;
  return oss.str();
}
template <typename T>
inline bool chmin(T &a, const T &b) {
  if (b < a) {
    a = b;
    return true;
  }
  return false;
}
template <typename T>
inline bool chmax(T &a, const T &b) {
  if (a < b) {
    a = b;
    return true;
  }
  return false;
}
class UnionFind {
 private:
  const int N;
  vector<int> parent;
  vector<int> rank;
  int groups_;
  std::vector<int> sizes;

 public:
  UnionFind(int n) : N(n), parent(N), rank(N, 0), groups_(N), sizes(N, 1) {
    std::iota(parent.begin(), parent.end(), 0);
    return;
  }
  int find(int x) {
    if (parent[x] == x) {
      return x;
    }
    return parent[x] = find(parent[x]);
  }
  bool same(int x, int y) { return find(x) == find(y); }
  bool unite(int x, int y) {
    x = find(x);
    y = find(y);
    if (x == y) {
      return false;
    }
    if (rank[x] < rank[y]) {
      parent[x] = y;
      sizes[y] += sizes[x];
    } else {
      parent[y] = x;
      sizes[x] += sizes[y];
      if (rank[x] == rank[y]) {
        ++rank[x];
      }
    }
    --groups_;
    return true;
  }
  int groups() const { return groups_; }
  int groupSize(const int x) { return sizes[find(x)]; }
};
int main() {
  cin.tie(0);
  ios::sync_with_stdio(false);
  cout << setprecision(12) << fixed;
  int N, M;
  in_impl(N, M);
  ;
  VI X(N);
  cin >> X;
  VI A(M), B(M), Y(M);
  VVI G(N);
  for (int i = (int)(0); i < (int)(M); ++i) {
    cin >> A[i] >> B[i] >> Y[i];
    --A[i], --B[i];
    G[A[i]].push_back(i);
    G[B[i]].push_back(i);
  }
  VI E(M);
  iota(begin(E), end(E), 0);
  sort(begin(E), end(E), [&](const int e, const int f) { return Y[e] < Y[f]; });
  VI possibly_heaviest(M);
  {
    UnionFind uf(N);
    VT<LL> weights(begin(X), end(X));
    for (auto &&e : E) {
      const int u = A[e], v = B[e];
      if (!uf.same(u, v)) {
        const LL w = weights[uf.find(u)] + weights[uf.find(v)];
        uf.unite(u, v);
        weights[uf.find(u)] = w;
      }
      const LL w = weights[uf.find(u)];
      possibly_heaviest[e] = Y[e] <= w;
    }
  }
  reverse(begin(E), end(E));
  VI use_edge(M);
  for (auto &&e : E) {
    if (use_edge[e] || !possibly_heaviest[e]) {
      continue;
    }
    use_edge[e] = true;
    queue<int> que;
    que.push(A[e]);
    que.push(B[e]);
    VI visited(N);
    visited[A[e]] = visited[B[e]] = true;
    while (!que.empty()) {
      const int u = que.front();
      que.pop();
      for (auto &&f : G[u]) {
        const int v = A[f] == u ? B[f] : A[f];
        if (Y[e] < Y[f] || visited[v]) {
          continue;
        }
        use_edge[f] = visited[v] = true;
        que.push(v);
      }
    }
  }
  cout << count(begin(use_edge), end(use_edge), 0) << endl;
  return 0;
}
