#include <cstdio>
#include <cstring>
#include <cmath>
#include <cassert>
#include <vector>
#include <string>
#include <set>
#include <map>
#include <queue>
#include <stack>
#include <algorithm>
using namespace std;


typedef long long i64;
const int inf = (int)1.05e9;

struct UnionFind {

	vector<int> par;

	void init(int n)
	{
		par.resize(n);
		for(int i = 0; i < n; ++i) {
			par[i] = i;
		}
	}

	int root(int x)
	{
		if(par[x] == x) {
			return x;
		} else {
			return par[x] = root(par[x]);
		}
	}

	bool same(int a, int b)
	{
		return root(a) == root(b);
	}

	int unite(int a, int b)
	{
		a = root(a);
		b = root(b);

		if(a != b) {
			par[b] = a;
		}

		return a;
	}
};

struct Data {
	int num_edge;
	int prev_ok;
	i64 max_edge;
	i64 sum_vertex;
};

int main()
{
	int n, m;
	vector<int> xs;
	vector<pair<i64, pair<int,int>>> edges;

	scanf("%d%d", &n, &m);
	xs.resize(n);
	for(int i = 0; i < n; ++i) {
		scanf("%d", &xs[i]);
	}
	for(int i = 0; i < m; ++i) {
		int a, b;
		i64 y;
		scanf("%d%d%lld", &a, &b, &y);
		edges.push_back({y, {a - 1, b - 1}});
	}

	sort(edges.begin(), edges.end());

	int ans = 0;
	UnionFind uf;

	uf.init(n);

	vector<Data> data(n);

	for(int i = 0; i < n; ++i) {
		data[i].num_edge = 0;
		data[i].max_edge = 0;
		data[i].sum_vertex = xs[i];
		data[i].prev_ok = 0;
	}

	for(auto& e : edges) {

		int x = e.second.first;
		int y = e.second.second;
		i64 w = e.first;

		int a = uf.root(x);
		int b = uf.root(y);

		if(a == b) {

			data[a].num_edge += 1;
			data[a].max_edge = max(data[a].max_edge, w);

		} else {

			int c = uf.unite(a, b);
			a = c;

			data[a].num_edge += data[b].num_edge + 1;
			data[a].max_edge = max(max(data[a].max_edge, data[b].max_edge), w);
			data[a].sum_vertex += data[b].sum_vertex;
			data[a].prev_ok += data[b].prev_ok;

		}

		if(data[a].max_edge <= data[a].sum_vertex) {
			ans = ans - data[a].prev_ok + data[a].num_edge;
			data[a].prev_ok = data[a].num_edge;
		}
	}

	printf("%d\n", m - ans);

	return 0;
}

/* waffle */
