#include <bits/stdc++.h>
#define SORT(x) sort((x).begin(), (x).end())
#define ALL(x) (x).begin(), (x).end()
#define rep(i, n) for (ll i = 0; i < n; i++)
#define reps(i, m, n) for (ll i = m; i < n; i++)
#define repr(i, m, n) for (ll i = m; i >= n; i--)
#define de(x) cout << #x << "=" << x << endl;
#define SP << " " <<
template <class T> bool maxi(T &a, const T &b) {
    if (a < b) { a = b; return 1;} return 0;}
template <class T> bool mini(T &a, const T &b) {
    if (b < a) { a = b; return 1;} return 0;}
#define dame {cout<< "-1" <<"\n"; return;}
#define INF2 1000000000000000037
#define INF  1000000007
#define MOD  1000000007
using namespace std;
using ll = long long;
using ld = long double;
using P  = pair<ll,ll>;
//--GLOBAL---------------------------------
vector<ll> node(101010);
vector<ll> X(101010);
vector<ll> numY(101010);
struct UF {
    int N;
    vector<int> par;
    vector<int> rank;

    UF(int n) : N(n), par(N), rank(N,0) {
        rep(i,N) {par[i] = i;}
    }

    int root(int x) {
        if (par[x] == x) return x;
        else {
            int r = root(par[x]); //根まで遡りながら経路圧縮
            return par[x] = r;
        }
    }
    bool issame(int x, int y) {
        return root(x) == root(y);
    }
    bool merge(int x, int y) {
        x = root(x); y = root(y);
        if (x == y) return false;
        if (rank[x] < rank[y]) swap(x, y);
        if (rank[x] == rank[y]) ++rank[x];
        par[y] = x; //ランクの小さい方に接続
        node[x]+=node[y];
        return true;
    }
};

vector<ll> tukau(101010);
ll ima;

struct edge{ll to; ll num;};
struct graph{
    ll N;
    vector<vector<edge> > G;
    vector<bool> used;

    graph(ll n): N(n), G(N), used(N,false) {}

    void ade(ll s, ll t, ll num){
        G[s].emplace_back((edge){t,num});
        G[t].emplace_back((edge){s,num}); //無向ならON
    }

    void dfs(ll v=0){
        used[v]=true;
        for(auto E : G[v]){
            if(!tukau[E.num] and ima>=numY[E.num]){
                tukau[E.num]=1;
                dfs(E.to);
            }
        }
    }
};
//--MAIN-----------------------------------
void Main() {
    ll N,M; cin>>N>>M;
    vector<P> Ynum;
    vector<ll> numA(M);
    vector<ll> numB(M);
    rep(i,N) cin>>X[i];
    rep(i,N){
        node[i]=X[i];
    }
    rep(i,M){
        ll a,b,y; cin>>a>>b>>y; --a,--b;
        numA[i]=a;
        numB[i]=b;
        numY[i]=y;
        Ynum.emplace_back(y,i);
    }
    UF uf(N);
    graph g(N);
    SORT(Ynum);
    vector<ll> tans;
    rep(i,M){
        ll y=Ynum[i].first;
        ll num=Ynum[i].second;
        ll a=numA[num];
        ll b=numB[num];
        uf.merge(a,b);
        g.ade(a,b,num);
        if(max(node[uf.root(a)],node[uf.root(b)])>=y) tans.emplace_back(num);
    }
    repr(i,tans.size()-1,0){
        ll doko=tans[i];
        ima=numY[doko];
        if(!g.used[numA[doko]]){
            g.dfs(numA[doko]);
        }
    }
    ll ans=M;
    rep(i,M){
        if(tukau[i]) --ans;
    }
    cout<< ans <<"\n";

}

//--START----------------------------------
int main() {
    cin.tie(nullptr);
    ios_base::sync_with_stdio(false);
    cout << fixed << setprecision(15);
    Main();
}
//-----------------------------------------


Measured memory_bytes: 17008