#include <iostream>
#include <string>
#include <algorithm>
#include <vector>
#include <functional>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <cstdio>
#include <cmath>
#include <tuple>
#define int long long
#define rep(i, n) for(i = 0; i < n; i++)
using namespace std;

struct Edge {
	int from, to, cost;
	Edge() {}
	Edge(int from, int to, int cost) {
		this->from = from;
		this->to = to;
		this->cost = cost;
	}
	bool operator<(Edge &r) {
		return cost < r.cost;
	}
};

struct UF {
	int par[100000];
	int sum[100000];
	int maxi[100000];
	int rank[100000];
	void init(int n, int x[]) { int i; rep(i, n) { par[i] = i; sum[i] = x[i]; maxi[i] = 0; rank[i] = 0; } }
	int root(int x) { if (par[x] == x) return x; return par[x] = root(par[x]); }
	void unit(int x, int y, int cst) {
		x = root(x);
		y = root(y);
		if (x != y) {
			if (rank[x] > rank[y]) swap(x, y);
			par[x] = y;
			sum[y] += sum[x];
			rank[y] = max(rank[y], rank[x] + 1);
		}
		maxi[y] = max({cst, maxi[x], maxi[y]});
	}
	bool same(int x, int y) { return root(x) == root(y); }
	int rootSum(int x) { return sum[root(x)]; }
	int rootMax(int x) { return maxi[root(x)]; }
};

int n, m;
int x[100000];
Edge edges[100000];
UF uf;

int solve() {
	int i, j;
	int ret = 0;
	
	uf.init(n, x);
	for (i = 0; i < m; i++) {
		int u = edges[i].from;
		int v = edges[i].to;
		int c = edges[i].cost + x[u] + x[v];
		uf.unit(u, v, c);
		
		rep(j, n) {
			if (uf.rootSum(j) < uf.rootMax(j)) {
				break;
			}
		}
		if (j == n) ret = i + 1;
	}
	return ret;
}

signed main() {
	int i;
	
	cin >> n >> m;
	rep(i, n) cin >> x[i];
	rep(i, m) {
		int u, v, d;
		cin >> u >> v >> d;
		u--; v--;
		edges[i] = Edge(u, v, d - (x[u] + x[v]));
	}
	sort(edges, edges + m);
	cout << m - solve() << endl;
	return 0;
}