#include <bits/stdc++.h>
using namespace std;
class UnionFind {
  vector<int> parent;
  vector<int> rank;

 public:
  UnionFind(int n) {
    parent = vector<int>(n, -1);
    rank = vector<int>(n, 0);
  }
  int find(int n) {
    vector<int> path;
    while (parent[n] != -1) {
      path.push_back(n);
      n = parent[n];
    }
    for (vector<int>::iterator it = path.begin(); it != path.end(); it++) {
      parent[*it] = n;
      rank[*it] = 0;
    }
    return n;
  }
  void unify(int x, int y) {
    int rx = find(x), ry = find(y);
    if (rx == ry) return;
    if (rank[rx] < rank[ry]) {
      parent[rx] = ry;
    } else {
      parent[ry] = rx;
      if (rank[rx] == rank[ry]) rank[rx]++;
    }
  }
  bool same(int x, int y) { return find(x) == find(y); }
};
const long long mod = 1e9 + 7;
struct edge {
  int from, to, cost;
  edge(int f, int t, int c) {
    from = f;
    to = t;
    cost = c;
  }
};
long long recur(const vector<edge> &edges, const vector<long long> &vcost) {
  const long long n = vcost.size();
  if (edges.empty()) {
    return 0;
  }
  vector<long long> costs;
  for (int i = 0; i < edges.size(); ++i) {
    costs.emplace_back(edges[i].cost);
  }
  sort(costs.begin(), costs.end());
  const long long midcost = costs[costs.size() / 2];
  UnionFind uf(n);
  for (int i = 0; i < edges.size(); ++i) {
    const auto edge = edges[i];
    if (edge.cost <= midcost) {
      uf.unify(edge.from, edge.to);
    }
  }
  vector<long long> unioncost(n);
  for (int i = 0; i < vcost.size(); ++i) {
    unioncost[uf.find(i)] += vcost[i];
  }
  bool ok = true;
  for (int i = 0; i < edges.size(); ++i) {
    const auto edge = edges[i];
    if (edge.cost <= midcost) {
      ok &= unioncost[uf.find(edge.from)] >= midcost;
    }
  }
  if (ok) {
    vector<long long> newvcost(n);
    for (int i = 0; i < n; ++i) {
      newvcost[i] = unioncost[uf.find(i)];
    }
    vector<edge> newedges;
    for (int i = 0; i < edges.size(); ++i) {
      const auto edge = edges[i];
      if (edge.cost > midcost) {
        newedges.emplace_back(uf.find(edge.from), uf.find(edge.to), edge.cost);
      }
    }
    return recur(newedges, newvcost);
  } else {
    long long ans = 0;
    vector<vector<edge>> subedges(n);
    for (int i = 0; i < edges.size(); ++i) {
      const auto edge = edges[i];
      if (edge.cost < midcost) {
        subedges[uf.find(edge.from)].push_back(edge);
      } else {
        ans += 1;
      }
    }
    for (int i = 0; i < subedges.size(); ++i) {
      ans += recur(subedges[i], vcost);
    }
    return ans;
  }
}
int main() {
  long long n, m;
  cin >> n >> m;
  vector<long long> vcost(n);
  for (int i = 0; i < n; ++i) {
    cin >> vcost[i];
  }
  vector<edge> edges;
  for (int i = 0; i < m; ++i) {
    long long a, b, y;
    cin >> a >> b >> y;
    a--;
    b--;
    edges.emplace_back(a, b, y);
  }
  cout << recur(edges, vcost) << endl;
  return 0;
}
