#include <bits/stdc++.h>
using namespace std;
const int INFL = (int)1e9;
const long long int INFLL = (long long int)1e18;
const double INFD = numeric_limits<double>::infinity();
const double PI = 3.14159265358979323846;
bool nearlyeq(double x, double y) { return abs(x - y) < 1e-9; }
bool inrange(int x, int t) { return x >= 0 && x < t; }
long long int rndf(double x) {
  return (long long int)(x + (x >= 0 ? 0.5 : -0.5));
}
long long int floorsqrt(double x) {
  long long int m = (long long int)sqrt(x);
  return m + (m * m <= (long long int)(x) ? 0 : -1);
}
long long int ceilsqrt(double x) {
  long long int m = (long long int)sqrt(x);
  return m + ((long long int)x <= m * m ? 0 : 1);
}
long long int rnddiv(long long int a, long long int b) {
  return (a / b + (a % b * 2 >= b ? 1 : 0));
}
long long int ceildiv(long long int a, long long int b) {
  return (a / b + (a % b == 0 ? 0 : 1));
}
long long int gcd(long long int m, long long int n) {
  if (n == 0)
    return m;
  else
    return gcd(n, m % n);
}
struct graph_t {
  int n;
  int m;
  vector<pair<int, int>> edges;
  vector<long long int> vals;
  vector<long long int> costs;
  vector<long long int> caps;
};
class Prim {
 private:
  struct node {
    int id;
    bool done;
    vector<int> to_eid;
    vector<int> to;
    vector<long long int> costs;
    int from_eid;
    int from;
    long long int d;
  };
  struct pq_t {
    int id;
    long long int d;
    bool operator<(const pq_t &another) const {
      return d != another.d ? d > another.d : id > another.id;
    }
  };
  vector<node> nodes;
  int n, m, root;

 public:
  Prim(graph_t G, int start) {
    n = G.n;
    m = G.edges.size();
    nodes.resize(n);
    for (int i = 0; i < (int)(n); i++)
      nodes[i] = {i, false, {}, {}, {}, -1, -1, LLONG_MAX};
    for (int i = 0; i < (int)(m); i++) {
      nodes[G.edges[i].first].to_eid.push_back(i);
      nodes[G.edges[i].first].to.push_back(G.edges[i].second);
      nodes[G.edges[i].first].costs.push_back(G.costs[i]);
      nodes[G.edges[i].second].to_eid.push_back(i - m);
      nodes[G.edges[i].second].to.push_back(G.edges[i].first);
      nodes[G.edges[i].second].costs.push_back(G.costs[i]);
    }
    root = start;
    nodes[root].d = 0;
    priority_queue<pq_t> pq;
    pq.push({nodes[root].id, nodes[root].d});
    while (pq.size()) {
      node *a = &nodes[pq.top().id];
      pq.pop();
      if (nodes[a->id].done) continue;
      nodes[a->id].done = true;
      for (int j = 0; j < (int)(a->to.size()); j++) {
        node *b = &nodes[a->to[j]];
        if (b->done) continue;
        long long int buf = a->costs[j];
        if (buf < b->d) {
          b->d = buf;
          b->from_eid = a->to_eid[j];
          b->from = a->id;
          pq.push({b->id, b->d});
        }
      }
    }
    return;
  }
  vector<pair<int, int>> get_tree_idpair() {
    vector<pair<int, int>> ret;
    for (int i = 0; i < (int)(n); i++) {
      if (i != root) ret.push_back({nodes[i].from, i});
    }
    return ret;
  }
  vector<int> get_tree_eid() {
    vector<int> ret;
    for (int i = 0; i < (int)(n); i++) {
      if (i != root) {
        ret.push_back(nodes[i].from_eid);
        if (ret.back() < 0) ret.back() += m;
      }
    }
    return ret;
  }
  long long int get_weight() {
    long long int ret = 0;
    for (int i = 0; i < (int)(n); i++) {
      if (i != root) ret += nodes[i].d;
    }
    return ret;
  }
};
struct tree_t {
  int n;
  vector<pair<int, int>> edges;
  vector<long long int> vals;
  vector<long long int> costs;
};
class Tree {
 private:
  struct node {
    int id;
    vector<int> childs;
    int parent = -1;
    int deg = -1;
    int eid = -1;
    int subtree_n = 1;
    long long int val;
    long long int cost;
    bool operator<(const node &another) const {
      return deg != another.deg ? deg < another.deg : id < another.id;
    }
  };
  struct edgeinfo {
    int eid;
    int to;
    long long int cost;
  };
  int n;
  static const long long int init_val = 0;
  static const long long int init_cost = 1;
  vector<vector<edgeinfo>> edges;
  void tree_construction() {
    leaves = {};
    queue<int> que;
    que.push(root);
    while (que.size()) {
      int a = que.front();
      que.pop();
      deg_order.push_back(a);
      if (a == Tree::root) nodes[a].deg = 0;
      int leaf_flag = true;
      for (int i = 0; i < (int)(edges[a].size()); i++) {
        int b = edges[a][i].to;
        if (nodes[b].deg != -1) {
          nodes[a].parent = b;
          nodes[a].eid = edges[a][i].eid;
          nodes[a].cost = edges[a][i].cost;
          nodes[a].deg = nodes[b].deg + 1;
        } else {
          leaf_flag = false;
          nodes[a].childs.push_back(b);
          que.push(b);
        }
      }
      if (leaf_flag) leaves.push_back(a);
    }
    for (int i = (int)(n)-1; i >= 0; i--) {
      int a = deg_order[i];
      for (int j = 0; j < (int)(nodes[a].childs.size()); j++) {
        int b = nodes[a].childs[j];
        nodes[a].subtree_n += nodes[b].subtree_n;
      }
    }
  }

 public:
  vector<node> nodes;
  vector<int> deg_order;
  vector<int> leaves;
  int root;
  Tree(tree_t T, int root) {
    n = T.n;
    nodes.resize(n);
    for (int i = 0; i < (int)(n); i++) {
      nodes[i].id = i;
      nodes[i].val = (int)(T.vals.size()) > i ? T.vals[i] : init_val;
      nodes[i].cost = init_cost;
    }
    edges.resize(n);
    for (int i = 0; i < (int)(n - 1); i++) {
      edges[T.edges[i].first].push_back(
          {i, T.edges[i].second,
           ((int)(T.costs.size()) > i ? T.costs[i] : init_cost)});
      edges[T.edges[i].second].push_back(
          {i, T.edges[i].first,
           ((int)(T.costs.size()) > i ? T.costs[i] : init_cost)});
    }
    Tree::root = root;
    tree_construction();
    return;
  }
  long long int get_sum(int a, int from) {
    long long int ret = nodes[a].val;
    if (nodes[a].cost != -1 && a != root && nodes[a].parent != from)
      ret += get_sum(nodes[a].parent, a);
    for (auto b : nodes[a].childs) {
      if (nodes[b].cost != -1 && b != from) ret += get_sum(b, a);
    }
    return ret;
  }
  void get_cc(int a, int from, vector<int> &ret) {
    ret.push_back(a);
    if (nodes[a].cost != -1 && a != root && nodes[a].parent != from)
      get_cc(nodes[a].parent, a, ret);
    for (auto b : nodes[a].childs) {
      if (nodes[b].cost != -1 && b != from) get_cc(b, a, ret);
    }
  }
  vector<pair<int, long long int>> solve() {
    long long int buf = get_sum(0, -1);
    vector<long long int> sum(n, buf);
    vector<pair<long long int, int>> w_costs;
    for (int i = 0; i < (int)(n); i++) {
      if (i == root)
        continue;
      else
        w_costs.push_back({nodes[i].cost, i});
    }
    sort(w_costs.begin(), w_costs.end());
    for (int i = (int)(w_costs.size()) - 1; i >= 0; i--) {
      long long int c = w_costs[i].first;
      long long int a = w_costs[i].second;
      int b = nodes[a].parent;
      if (c <= sum[a])
        continue;
      else {
        nodes[a].cost = -1;
        long long int buf0 = get_sum(a, b), buf1 = get_sum(b, a);
        vector<int> nbuf0, nbuf1;
        get_cc(a, b, nbuf0);
        get_cc(a, b, nbuf1);
        for (int j = 0; j < (int)(nbuf0.size()); j++) sum[nbuf0[j]] = buf0;
        for (int j = 0; j < (int)(nbuf1.size()); j++) sum[nbuf1[j]] = buf1;
      }
    }
    vector<pair<int, long long int>> ret(n);
    vector<bool> done(n, false);
    int cnt = 0;
    for (int i = 0; i < (int)(n); i++) {
      if (done[i]) continue;
      cnt++;
      long long int buf0 = get_sum(i, -1);
      vector<int> nbuf;
      get_cc(i, -1, nbuf);
      for (int j = 0; j < (int)(nbuf.size()); j++) {
        done[nbuf[j]] = true;
        ret[nbuf[j]] = {cnt, buf0};
      }
    }
    return ret;
  }
};
int main() {
  ios::sync_with_stdio(false);
  cin.tie(0);
  ;
  graph_t G;
  cin >> G.n >> G.m;
  for (int i = 0; i < (int)(G.n); i++) {
    long long int x;
    cin >> x;
    G.vals.push_back(x);
  }
  for (int i = 0; i < (int)(G.m); i++) {
    int s, t;
    cin >> s >> t;
    s--;
    t--;
    long long int c;
    cin >> c;
    G.edges.push_back({s, t});
    G.costs.push_back(c);
  }
  Prim prim(G, 0);
  vector<int> eids = prim.get_tree_eid();
  tree_t T;
  T.n = G.n;
  T.vals = G.vals;
  for (int i = 0; i < (int)(T.n - 1); i++) {
    T.edges.push_back(G.edges[eids[i]]);
    T.costs.push_back(G.costs[eids[i]]);
  }
  Tree tree(T, 0);
  vector<pair<int, long long int>> record = tree.solve();
  int ans = 0;
  for (int i = 0; i < (int)(G.m); i++) {
    int s = G.edges[i].first;
    int t = G.edges[i].second;
    if (record[s].first != record[t].first || G.costs[i] > record[s].second)
      ans++;
  }
  cout << ans << endl;
}
