// #pragma GCC optimize("-O0")
#include <algorithm>
#include <iostream>
#include <vector>
using namespace std;
typedef long long llong;
typedef unsigned int uint;
struct Edge
{
    int u, v;
    llong w;
};

llong x[100'000];

int par[100'000], sz[100'000];
llong sum[100'000];
int e[100'000];
void MakeSet(int v)
{
    par[v] = v;
    sz[v] = 1;
    sum[v] = x[v];
    e[v] = 0;
}
int Root(int v)
{
    return (par[v] == v) ? v : (par[v] = Root(par[v]));
}
void Union(int u, int v)
{
    u = Root(u); v = Root(v);
    if (u == v) return;
    if (sz[u] > sz[v])
        swap(u, v);
    par[u] = v;
    sz[v] += sz[u];
    sum[v] += sum[u];
    e[v] += e[u];
    e[u] = 0;
}
int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0); cout.tie(0);
    int n, m;
    cin >> n >> m;
    for (int i = 0; i < n; ++i)
    {
        cin >> x[i];
        MakeSet(i);
    }
    vector<Edge> edges;
    for (int j = 0; j < m; ++j)
    {
        Edge edge;
        cin >> edge.u >> edge.v >> edge.w;
        --edge.u; --edge.v;
        edges.push_back(edge);
    }
    sort(edges.begin(), edges.end(), [](const Edge& a, const Edge& b) {
         return a.w < b.w;
    });
    int ans = n;
    for (Edge edge: edges)
    {
        int u = edge.u, v = edge.v, w = edge.w;
        Union(u, v);
        int root = Root(v);
        ++e[root];
        if (sum[root] >= w)
        {
            ans -= e[root];
            e[root] = 0;
        }
    }
    cout << ans;
}
