#include <bits/stdc++.h>
using namespace std;
long long int ppow(long long int i, long long int j) {
  long long int res = 1LL;
  while (j) {
    if ((j & 1LL)) {
      res *= i;
      if (res >= 1000000007) {
        res %= 1000000007;
      }
    }
    j >>= 1;
    i *= i;
    if (i >= 1000000007) {
      i %= 1000000007;
    }
  }
  return res;
}
long long int gcd(long long int a, long long int b) {
  if (a > b) {
    swap(a, b);
  }
  while (a) {
    swap(a, b);
    a %= b;
  }
  return b;
}
long long int lcm(long long int a, long long int b) {
  return a / gcd(a, b) * b;
}
int n;
int m;
vector<long long int> node;
struct st {
  int a;
  int b;
  long long int cost;
};
vector<st> ed;
bool cmp(st a, st b) { return a.cost < b.cost; }
struct UF {
  vector<int> belong;
  vector<long long int> size;
  vector<long long int> mx;
  vector<set<int> > wait;
  vector<multiset<long long int> > que;
  int gross;
  void resize(int n) {
    belong.assign(n + 1, -1);
    mx.resize(n + 1, 0);
    que.assign(n, multiset<long long int>());
    wait.assign(n, set<int>());
    size = node;
    gross = 0;
  }
  inline int root(int b) {
    if (belong[b] == -1) {
      return b;
    }
    belong[b] = root(belong[b]);
    return belong[b];
  }
  void merge(int a, int b, long long int cost) {
    a = root(a);
    b = root(b);
    if (a == b) return;
    belong[a] = b;
    size[b] += size[a];
    mx[b] = max(mx[b], mx[a]);
    mx[b] = max(mx[b], cost);
    if (wait[b].size() < wait[a].size()) swap(wait[a], wait[b]);
    for (auto el : wait[a]) {
      if (wait[b].count(el)) {
        que[b].insert(ed[el].cost);
        wait[b].erase(el);
      } else {
        wait[b].insert(el);
      }
    }
    wait[a].clear();
    if (que[b].size() < que[a].size()) swap(que[a], que[b]);
    for (auto el : que[a]) {
      que[b].insert(el);
    }
    que[a].clear();
    while (que[b].size() && (*que[b].begin()) <= size[b]) {
      que[b].erase(que[b].begin());
      gross++;
    }
  }
  bool valid(int a) {
    a = root(a);
    return mx[a] > size[a];
  }
  void dum(int a, long long int z) {
    a = root(a);
    if (z <= size[a]) {
      gross++;
      return;
    }
    que[a].insert(z);
  }
};
UF uf;
bool make(int mid) {
  uf.resize(n);
  int dum = 0;
  int MM = 0;
  for (int i = 0; i < ed.size(); i++) {
    uf.wait[ed[i].a].insert(i);
    uf.wait[ed[i].b].insert(i);
  }
  for (int i = 0; i < mid; i++) {
    if (uf.root(ed[i].a) != uf.root(ed[i].b)) {
      dum -= uf.valid(ed[i].a);
      dum -= uf.valid(ed[i].b);
      uf.merge(ed[i].a, ed[i].b, ed[i].cost);
      if (uf.valid(ed[i].a)) {
        dum++;
      }
      if (dum == 0) {
        MM = max(MM, uf.gross);
      }
    } else {
    }
  }
  printf("%d\n", ed.size() - MM);
  return true;
}
int main() {
  cin >> n >> m;
  uf.resize(n);
  for (int i = 0; i < n; i++) {
    int a;
    scanf("%d", &a);
    node.push_back(a);
  }
  for (int i = 0; i < m; i++) {
    int a, b, y;
    scanf("%d%d%d", &a, &b, &y);
    a--;
    b--;
    ed.push_back({a, b, y});
  }
  sort(ed.begin(), ed.end(), cmp);
  make(ed.size());
  return 0;
}
