#include <bit>
#include <bitset>
#include <assert.h>
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <sstream>
#include <iostream>
#include <set>
#include <map>
#include <vector>
#include <math.h>
#include <stdlib.h>
#include <queue>
#include <stack>


typedef long double ld;
typedef long long ll;

using namespace std;

#define MAXN (1 << 18)

struct edge {
	int v1, v2;
	ll w;

	edge(int tv1 = 0, int tv2 = 0, ll tw = 0) {
		v1 = tv1;
		v2 = tv2;
		w = tw;
	}

	bool operator<(const edge & e) const {
		return w < e.w;
	}
	
	void read() {
		cin >> v1 >> v2 >> w;
		v1--;
		v2--;
	}
};

edge e[MAXN];
ll x[MAXN];
int n, m;

int p[MAXN];
ll sumv[MAXN];
ll maxw[MAXN];
int id[MAXN];
bool ok[MAXN];

int idcnt;
vector<int> t[MAXN];
int v[MAXN];

int find(int v) {
	if (v == p[v]) {
		return v;	
	}
	int ret = find(p[v]);
	p[v] = ret;
	return ret;
}


void merge(int v1, int v2, ll w) {
	v1 = find(v1);
	v2 = find(v2);
	//cerr << v1 << " " << v2 << " " << id[v1] << " " << id[v2] << endl;
	if (v1 != v2) {
		p[v2] = v1;
		sumv[v1] += sumv[v2];
		maxw[v1] = max(maxw[v1], maxw[v2]);
		t[idcnt].push_back(id[v1]);
		t[idcnt].push_back(id[v2]);
	} else {
		t[idcnt].push_back(id[v1]);
	}
	maxw[v1] = max(maxw[v1], w);
	id[v1] = idcnt;	
	ok[idcnt] = (maxw[v1] <= sumv[v1]);
	idcnt++;
}

int ret = 0;

void dfs(int cur) {
	v[cur] = 1;
//	cerr << cur << endl;
	if (ok[cur]) {
		return;
	}
	ret++;
	for (auto& nnext : t[cur]) {
		if (!v[nnext]) {
			dfs(nnext);
		}
	}
}

int main() {
	cin >> n >> m;
	for (int i = 0; i < n; i++) {
		cin >> x[i];
		p[i] = i;
		sumv[i] = x[i];
		maxw[i] = 0;
		id[i] = i;
		ok[i] = true;
	}
	idcnt = n;
	for (int i = 0; i < m; i++) {
		e[i].read();
	}
	sort(e, e + m);
	for (int i = 0; i < m; i++) {
		merge(e[i].v1, e[i].v2, e[i].w);
	}
	dfs(idcnt - 1);
	cout << ret << endl;
	return 0;
}
