#include <bits/stdc++.h>
using namespace std;
int X[100001];
class UnionFindTree {
 private:
  int N;
  int *rootnum;
  int *rank;
  int *unionnum;

 public:
  UnionFindTree(int n) {
    N = n;
    rootnum = new int[N];
    rank = new int[N];
    unionnum = new int[N];
    for (int i = 0; i < N; i++) {
      rootnum[i] = i;
      rank[i] = 0;
      unionnum[i] = 1;
    }
  }
  int Find(int j) {
    if (rootnum[j] == j) {
      return j;
    } else {
      return rootnum[j] = Find(rootnum[j]);
    }
  }
  void Union(int i, int j) {
    int x = Find(i);
    int y = Find(j);
    if (x == y) return;
    N--;
    if (rank[x] < rank[y]) {
      rootnum[y] = x;
      unionnum[x] += unionnum[y];
    } else {
      rootnum[x] = y;
      unionnum[y] += unionnum[x];
      if (rank[x] == rank[y]) rank[x]++;
    }
  }
  int Num(int j) {
    int x = Find(j);
    return unionnum[x];
  }
  int UnionNum() { return N; }
  ~UnionFindTree() {
    delete rootnum;
    delete rank;
    delete unionnum;
  }
};
vector<pair<pair<int, int>, int>> edges[10001];
bool used[100001];
bool arrived[100001];
void dfs(int a, int y) {
  arrived[a] = true;
  for (int ei = 0; ei < (int)edges[a].size(); ei++) {
    int y2 = edges[a][ei].first.first;
    int b = edges[a][ei].first.second;
    int i = edges[a][ei].second;
    if (y2 <= y) {
      used[i] = true;
      if (arrived[b] == false) {
        dfs(b, y);
      }
    }
  }
}
int main() {
  int N, M;
  cin >> N >> M;
  for (int i = 0; i < N; i++) cin >> X[i];
  vector<pair<int, pair<int, int>>> E;
  for (int i = 0; i < M; i++) {
    int A, B, Y;
    cin >> A >> B >> Y;
    A--;
    B--;
    E.push_back(make_pair(Y, make_pair(A, B)));
  }
  sort(E.begin(), E.end());
  for (int i = 0; i < M; i++) {
    int Y = E[i].first;
    int A = E[i].second.first;
    int B = E[i].second.second;
    edges[A].push_back(make_pair(make_pair(Y, B), i));
    edges[B].push_back(make_pair(make_pair(Y, A), i));
  }
  for (int i = 0; i < N; i++) {
    sort(edges[i].begin(), edges[i].end());
  }
  UnionFindTree uft(N);
  int cost[N];
  for (int i = 0; i < N; i++) cost[i] = X[i];
  bool flag[M];
  memset(flag, false, sizeof(flag));
  for (int i = 0; i < M; i++) {
    int y = E[i].first;
    int a = E[i].second.first;
    int b = E[i].second.second;
    int ar = uft.Find(a);
    int br = uft.Find(b);
    if (ar != br) {
      uft.Union(a, b);
      int abr = uft.Find(a);
      cost[abr] = cost[ar] + cost[br];
    }
    int abr2 = uft.Find(a);
    if (cost[abr2] >= y) {
      flag[i] = true;
    }
  }
  memset(used, false, sizeof(used));
  int ans = 0;
  for (int i = M - 1; i >= 0; i--) {
    int y = E[i].first;
    int a = E[i].second.first;
    if (used[i] == false && flag[i] == true) {
      memset(arrived, false, sizeof(arrived));
      dfs(a, y);
    } else if (!used[i]) {
      ans++;
    }
  }
  cout << ans << endl;
  return 0;
}
