#include <bits/stdc++.h>

using namespace std;
using int64 = long long;

constexpr int DEBUG = 0;

struct WEdge {
  int v1, v2;
  int64 w;
  int id;
  WEdge(int v1, int v2, int64 w, int id): v1(v1), v2(v2), w(w), id(id) {}
};

class UFSet {
 private:
  vector<int> ranks;
  vector<int> prevs;

 public:
  UFSet(int n) : ranks(n), prevs(n) {
    for (int i = 0; i < n; i++) prevs[i] = i;
  }

  // Returns a root of a tree which x belongs to.
  int Find(int x) {
    if (x != prevs[x]) prevs[x] = Find(prevs[x]);
    return prevs[x];
  }

  // Merges a set which x blongs to and a set which y belongs to.
  void Union(int x, int y) {
    int x_root = Find(x);
    int y_root = Find(y);
    if (ranks[x_root] > ranks[y_root]) {
      prevs[y_root] = prevs[x_root];
    } else if (ranks[x_root] < ranks[y_root]) {
      prevs[x_root] = prevs[y_root];
    } else if (prevs[x_root] != prevs[y_root]) {
      prevs[y_root] = prevs[x_root];
      ranks[x_root]++;
    }
  }
};

struct Component {
  int64 v_weight;
  int key_edge;
  Component* child_1;
  Component* child_2;
};

int main() {
  ios::sync_with_stdio(false);
  cin.tie(0);

  int n, m;
  cin >> n >> m;

  vector<int64> v_weights(n);
  for (int i = 0; i < n; i++) {
    cin >> v_weights[i];
  }

  vector<WEdge> edges;
  for (int i = 0; i < m; i++) {
    int v1, v2;
    int64 w;
    cin >> v1 >> v2 >> w;
    v1--;
    v2--;
    edges.emplace_back(v1, v2, w, -1);
  }
  sort(edges.begin(), edges.end(), [](WEdge e1, WEdge e2) {
    return e1.w < e2.w;
  });
  // Assign IDs after sort.
  for (int i = 0; i < m; i++) {
    edges[i].id = i;
  }

  vector<int> mst_edges;
  vector<Component*> components(n, nullptr);
  for (int i = 0; i < n; i++) {
    components[i] = new Component({v_weights[i], -1, nullptr, nullptr});
  }
  UFSet uf_set(n);
  for (const auto& e : edges) {
    if (DEBUG) {
      cout << "Test " << e.v1 << " " << e.v2 << endl;
    }
    if (uf_set.Find(e.v1) == uf_set.Find(e.v2)) continue;
    if (DEBUG) {
      cout << "ADD" << endl;
    }
    Component* c1 = components[uf_set.Find(e.v1)];
    Component* c2 = components[uf_set.Find(e.v2)];
    int64 v_sum = c1->v_weight + c2->v_weight;

    uf_set.Union(e.v1, e.v2);

    mst_edges.push_back(e.id);
    components[uf_set.Find(e.v1)] = new Component({v_sum, e.id, c1, c2});
  }
  if (DEBUG) {
    cout << "mst_edges.size(): " << mst_edges.size() << endl;
  }

  vector<int> removed(m);
  Component* root = components[uf_set.Find(0)];
  function<void(Component*)> dfs_fn = [&](const Component* component) {
    if (component->key_edge == -1) return;
    if (component->v_weight < edges[component->key_edge].w) {
      if (DEBUG) {
        cout << "Remove MST Edge: (" << edges[component->key_edge].v1 << ", "
             << edges[component->key_edge].v2 << ")" << endl;
      }
      removed[component->key_edge] = 1;
      dfs_fn(component->child_1);
      dfs_fn(component->child_2);
    }
  };
  dfs_fn(root);

  UFSet uf_set_2(n);
  vector<int64> component_weights(n);
  for (int i = 0; i < n; i++) {
    component_weights[i] = v_weights[i];
  }
  for (int mst_edge: mst_edges) {
    if (removed[mst_edge]) continue;
    if (DEBUG) cout << edges[mst_edge].v1 << " " << edges[mst_edge].v2 << endl;
    int c1 = uf_set_2.Find(edges[mst_edge].v1);
    int c2 = uf_set_2.Find(edges[mst_edge].v2);
    uf_set_2.Union(c1, c2);
    component_weights[uf_set_2.Find(c1)] = component_weights[c1] + component_weights[c2];
  }

  for (int i = 0; i < n; i++) {
    if (DEBUG) cout << "i: " << i << " -> " << uf_set_2.Find(i) << endl;
  }

  int count = 0;
  for (const auto& edge : edges) {
    if (uf_set_2.Find(edge.v1) != uf_set_2.Find(edge.v2)) {
      count++;
    } else if (edge.w > component_weights[uf_set_2.Find(edge.v1)]) {
      count++;
    }
  }
  cout << count << endl;
}

Measured memory_bytes: 21744