#include<bits/stdc++.h>
using namespace std;
#ifndef d
#define d(...)
#endif
#define st first
#define nd second
#define pb push_back
#define siz(c) (int)(c).size()
#define all(c) (c).begin(), (c).end()
typedef long long LL;
typedef long double LD;
constexpr int INF=1e9+7;
constexpr LL INFL=1e18;
template<class L, class R> ostream &operator<<(ostream &os, pair<L,R> P) {
  return os << "(" << P.st << "," << P.nd << ")";
}
/*
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace __gnu_pbds;
template <typename T>
using ordered_set =
    tree<T, null_type, less<T>, rb_tree_tag,
         tree_order_statistics_node_update>;
*/

struct Edge {
	int a, b, v;
	
	bool operator < (const Edge& e) const {
		return v < e.v;
	}
	friend istream& operator >> (istream& in, Edge& e) {
		return in >> e.a >> e.b >> e.v;
	}
};
vector<Edge> edges;

constexpr int maxn = 100005;

int n, m, fu[maxn], cnt_edg[maxn];
LL x[maxn];
bool ok[maxn];

int fin(int a) {
	return fu[a] == a ? a : fu[a] = fin(fu[a]);
}

void un(int a, int b) {
	if(a == b) return;
	x[a] += x[b];
	cnt_edg[a] += cnt_edg[b];
	fu[b] = a;
}

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

	cin >> n >> m;
	for(int i=1; i<=n; i++)
		cin >> x[i];
	edges.resize(m);
	for(auto& e:edges)
		cin >> e;
	
	sort(all(edges));
	iota(fu, fu+n+1, 0);
	int ans = 0;
	for(int i=0; i<m; i++) {
		auto& e = edges[i];
		auto a = fin(e.a), b = fin(e.b);
		un(a, b);
		cnt_edg[a]++;
		if(x[a] >= e.v) {
			ans += cnt_edg[a];
			cnt_edg[a] = 0;
		}
	}
	
	cout << m - ans << "\n";
		
	




	return 0;
}
