#include <algorithm>
#include <iostream>
#include <vector>
#include <math.h>
#include <set>
#include <map>
#include <string>
#include <stack>
#include <queue>
#include <iomanip>
#include <numeric>
#include <tuple>
#include <bitset>
#include <complex>
#include <unistd.h>
#include <cassert>
#include <cctype>
#include <random>
#include <time.h>
#define _USE_MATH_DEFINES
#define _GLIBCXX_DEBUG
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> plglg;
typedef pair<double, ll> pdlg;
typedef tuple<int, int, int> tiii;
typedef tuple<ll, ll, ll> tlglglg;
typedef tuple<ll, ll, ll, ll> tlglglglg;
typedef tuple<double, double, double> tddd;
typedef complex<double> xy_t;
typedef vector<ll> vll;
typedef vector< vector<ll> > matrix;
#define REP(i, x, y) for(ll i = (ll)x; i < (ll)y; i++)
#define DREP(i, x, y, d) for(ll i = (ll)x; i < (ll)y; i += (ll)d)
#define PER(i, x, y) for(ll i = (ll)x; i > (ll)y; i--)
#define DPER(i, x, y, d) for(ll i = (ll)x; i > (ll)y; i -= (ll)d)
int dx[4] = {1, 0, -1, 0};
int dy[4] = {0, 1, 0, -1};
double pi = 3.141592653589793;
ll mod = 1000000007;
int intmax = 2147483647;
int intmin = -2147483648;
ll llmax = 9223372036854775807;
ll llmin = -9223372036854775807;
int iinf = intmax / 8;
ll inf = llmax / 8;
double eps = 1e-12;

struct persistentUnionFind {
    vector<int> parent;
    vector<int> sz;
    vector<int> height;
    vector<vector<plglg>> S;
    vector<ll> time;
    vector<ll> X;
    vector<ll> wt;
    vector<vector<plglg>> W;

    persistentUnionFind(int N, vector<ll> X) : parent(N, 0), sz(N, 1), height(N, 1),
                                 S(N, vector<plglg>(1, plglg(0, 1))),
                                 time(N, inf), X(X), wt(N),
                                 W(N, vector<plglg>()) {
        for (int i = 0; i < N; i++)
        {
            parent[i] = i;
            wt[i] = X[i];
            W[i].push_back(plglg(0, X[i]));
        }
    }

    int root(int x, ll t) {
        while (time[x] <= t) {
            x = parent[x];
        }
        return x;
    }

    bool unite(int x, int y, ll t) {
        int px = root(x, t);
        int py = root(y, t);
        if (px == py) {
            return false;
        }
        if (height[py] < height[px]) {
            parent[py] = px;
            time[py] = t;
            sz[px] += sz[py];
            S[px].push_back(plglg(t, sz[px]));
            wt[px] += wt[py];
            W[px].push_back(plglg(t, wt[px]));
        } else {
            parent[px] = py;
            time[px] = t;
            sz[py] += sz[px];
            S[py].push_back(plglg(t, sz[py]));
            wt[py] += wt[px];
            W[py].push_back(plglg(t, wt[py]));
            height[py] = max(height[py], height[px] + 1);
        }
        return true;
    }

    ll size(int x, ll t) {
        int y = root(x, t);
        int idx = lower_bound(S[y].begin(), S[y].end(), plglg(t, inf)) - S[y].begin() - 1;
        return S[y][idx].second;
    }

    ll weight(int x, ll t) {
        int y = root(x, t);
        int idx = lower_bound(W[y].begin(), W[y].end(), plglg(t, inf)) - W[y].begin() - 1;
        return W[y][idx].second;
    }
};

struct edge {
    ll to, cost, num;
};

int V;
vector<edge> G[1000000];
ll d[1000000];
map<ll, plglg> mp;

void addedge(int st, int ed, ll co, ll num) {
    edge e;
    e.to = ed;
    e.cost = co;
    e.num = num;
    G[st].push_back(e);
    mp[num] = plglg(st, G[st].size() - 1);
}

tlglglglg dat[100010];
bool used[100010];
bool usednode[100010];

int main() {
    cin.tie(0);
    ios::sync_with_stdio(false);
    ll N, M;
    cin >> N >> M;
    vector<ll> X(N);
    REP(i, 0, N) {
        cin >> X[i];
    }
    REP(i, 0, M) {
        ll a, b, y;
        cin >> a >> b >> y;
        dat[i] = tlglglglg(y, a - 1, b - 1, i);
    }
    fill(used, used + M, false);
    fill(usednode, usednode + M, false);
    sort(dat, dat + M);
    REP(i, 0, M) {
        tlglglglg t  = dat[i];
        ll a = get<1>(t);
        ll b = get<2>(t);
        ll y = get<0>(t);
        ll num = get<3>(t);
        addedge(a, b, y, num);
        addedge(b, a, y, num);
    }
    persistentUnionFind u(N, X);
    REP(i, 0, M) {
        tlglglglg t = dat[i];
        u.unite(get<1>(t), get<2>(t), i + 1);
    }
    ll ans = 0;
    // cout << "aaa" << endl;
    PER(i, M - 1, -1) {
        tlglglglg t = dat[i];
        // cout << get<0>(t) << " " << get<1>(t) << " " << get<2>(t) << " ";
        // cout << i << " " << u.weight(get<1>(t), i + 1) << endl;
        // cout << get<3>(t) << " " << used[get<3>(t)] << endl;
        if (used[get<3>(t)]) {
            continue;
        }
        if (u.weight(get<1>(t), i + 1) < get<0>(t)) {
            ans++;
        } else {
            queue<ll> que;
            plglg p = mp[get<3>(t)];
            edge e = G[p.first][p.second];
            used[get<3>(t)] = true;
            que.push(p.first);
            que.push(e.to);
            usednode[p.first] = true;
            usednode[e.to] = true;
            while (!que.empty()) {
                ll num = que.front();
                que.pop();
                REP(j, 0, G[num].size()) {
                    edge e = G[num][j];
                    if (used[e.num]) {
                        continue;
                    }
                    if (e.cost <= get<0>(t)) {
                        used[e.num] = true;
                        if (!usednode[e.to]) {
                            usednode[e.to] = true;
                            que.push(e.to);
                        }
                    }
                }
            }
        }
    }
    cout << ans << endl;
}


Measured memory_bytes: 62832