#include <cassert>
#include <iostream>
#include <functional>
#include <iomanip>
#include <set>
#include <unordered_map>
#include <map>
#include <queue>
#include <vector>
#include <deque>
#include <algorithm>
#include  <cstring>
#include <string>
#include <cmath> 
#include <random>

#pragma warning(disable: 4996)

using namespace std;
 
namespace Bigcat {
	template <typename T> inline void max_s(T&a, const T&b) { a = max(a, b); }
	template <typename T> inline void min_s(T&a, const T&b) { a = min(a, b); }

	template <typename T>  void sort_v(T & x) { sort(x.begin(), x.end()); }
	template <typename T>  void erase_dup(T & x) { x.erase(unique(x.begin(), x.end()), x.end()); }    // erase duplicate
	template <typename T, typename V>  int pos_l(const T & x, const V & v) { return lower_bound(x.begin(), x.end(), v) - x.begin(); }
	template <typename T, typename V>  int pos_u(const T & x, const V & v) { return upper_bound(x.begin(), x.end(), v) - x.begin(); }

	inline unsigned rand_g() {
		static mt19937 mt_rand((int)time(0));
		return mt_rand();
	}

	using LL = long long;


	using VI = vector<int>;
	using VVI = vector< VI >;
	using VL = vector<LL>;
	using PII = pair<int, int>;
	using VPII = vector< PII >;

}
using namespace Bigcat;
const int MAX = int ( 1e5 + 100 ) ;
const LL base = LL(1e9 + 7);
const LL INFL = 4223372036854775807LL;
const int INF = 1047483647;


struct Node {
	int a, b, y;
};
bool operator < (const Node & n0, const Node & n1) {
	return n0.y< n1.y;
}
LL zx[MAX];
vector<Node> es;
int bcj[2 * MAX];
LL  ty[2 * MAX], fi[2 * MAX];
bool isok[2 * MAX];
int lson[MAX], rson[MAX], par[MAX], belong[MAX];
bool ifc[MAX];

int findroot(int a) {
	if (bcj[a] == a) return a;
	return bcj[a] = findroot(bcj[a]);
}
void solve1() {

	LL result = 0;
	int n,m;

	cin >> n>>m;
	for (int i = 1; i <= n; ++i) {
		cin >> zx[i];
		ty[i] = zx[i];
	}
	es.resize(m);
	for (int i = 0; i < m; ++i) {
		auto & x = es[i];
		cin >> x.a >> x.b >> x.y;
	}
	sort(es.begin(), es.end());
	for (int i = 0; i < 2 * MAX; ++i) {
		bcj[i] = i;
	}
	int now = n;
	for (int i = 0; i < m; ++i) {
		auto x = es[i];
		int a = findroot(x.a);
		int b = findroot(x.b);
		if (a == b) {
			belong[i] = a;
			continue;
		}
		ifc[i] = true;
		lson[i] = a;
		rson[i] = b;
		++now;
		par[i] = now;
		bcj[a] = now;
		bcj[b] = now;
		ty[now] = ty[a] + ty[b];
	}

	for (int i = m - 1; i >= 0; --i) {
		if (ifc[i]) {
			int t = par[i];
			if (ty[t] >= es[i].y) {
				if (!isok[t]) {
					fi[t] = ty[t];
					isok[t] = true;
				}
			}
			if (isok[t]) {
				isok[lson[i]] = true;
				isok[rson[i]] = true;
				fi[lson[i]] = fi[t];
				fi[rson[i]] = fi[t];
			}
			else {
				result += 1;
			}
		}
	}
	for (int i = m - 1; i >= 0; --i) {
		if (!ifc[i]) {
			int t = belong[i];
			if (isok[t] == false) result += 1;
			else {
				if (fi[t] < es[i].y) result += 1;
			}
		}
	}
	cout << result << endl;

}
void solve() {
	int t = 1;
	//cin >> t;
	for (int i = 0; i < t; ++i) {
		solve1();
	}
    int x = 1;
}

int main() {
	const int inId = 0;
	const int outId = 0;
	if (inId>0) {
		cerr << "redirect stdin to input " << inId << endl;
		string s = "input";
		s += to_string(inId);
		s += ".txt";
		auto r = freopen(s.c_str(), "r", stdin);
		if (r == nullptr) {
			cerr << "invalid input file " << s << endl;;
			r = freopen("CON", "r", stdin);
		}
	}
	if (outId>0) {
		cerr << "redirect stdout to stdout " << outId << endl;
		string s = "stdout";
		s += to_string(outId);
		s += ".txt";
		auto r = freopen(s.c_str(), "w", stdout);
		if (r == nullptr) {
			cerr << "invalid output file " << s << endl;;
			r = freopen("CON", "w", stdout);
		}
	}
	ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0); // close sync between cout and printf
	cout.precision(10);
	solve();
}


Measured memory_bytes: 7552