#include <bits/stdc++.h>
using namespace std;

typedef long long ll;

struct Treap {
    Treap *lc,*rc,*fa;
    ll pri,key,val,sum;
    Treap(ll _key,ll _val):lc(NULL),rc(NULL),fa(NULL),pri(rand()),key(_key),val(_val),sum(_val){}
};

ll Sum(Treap* t) {
    return t?t->sum:0;
}

void pull(Treap* t) {
    if (!t) return;
    t->sum = Sum(t->lc) + Sum(t->rc) + t->val;
    t->fa = NULL;
    if (t->lc) {
        t->lc->fa = t;
    }
    if (t->rc) {
        t->rc->fa = t;
    }
}

Treap* merge(Treap* a,Treap* b) {
    if (!a || !b) return a?a:b;
    else if (a->pri > b->pri) {
        a->rc = merge(a->rc,b);
        pull(a);
        return a;
    }
    else {
        b->lc = merge(a,b->lc);
        pull(b);
        return b;
    }
}

void split(Treap* t,int k,Treap* &a,Treap* &b) {
    if (!t) a=b=NULL;
    else if (t->key <= k) {
        a=t;
        split(t->rc,k,a->rc,b);
        pull(a);
    }
    else {
        b=t;
        split(t->lc,k,a,b->lc);
        pull(b);
    }
}

const int N = 200006;
ll w[N];

struct Edge {
    ll a,b,c;
    bool on_mst;
    Edge(ll _a,ll _b,ll _c):a(_a),b(_b),c(_c),on_mst(false){}
};

bool operator<(const Edge &e1,const Edge &e2) {
    return e1.c < e2.c;
}

vector<int> G[N];

struct DJS {
    static const int N = 200006;
    int p[N];
    void init() {
        for (int i=0;i<N;++i) {
            p[i] = i;
        }
    }
    int Find(int x) {
        return p[x] == x?x:p[x] = Find(p[x]);
    }
    void Union(int x,int y) {
        p[ Find(x) ] = Find(y);
    }
} djs;

int pin[N],pout[N];
int rev[2*N];
int stamp=0;

void dfs(int now,int par) {
    ++stamp;
    pin[now] = stamp;
    rev[stamp] = now;
    for (int i:G[now]) {
        if (i == par) continue;
        dfs(i,now);
    }
    ++stamp;
    pout[now] = stamp;
    rev[stamp] = now;
}

Treap* p[2*N];
bool okay[2*N];

bool is_anc(int par,int son) {
    return pin[par] <= pin[son] && pout[son] <= pout[par];
}

Treap* find_root(Treap* t) {
    while (t->fa != NULL) t = t->fa;
    return t;
}

void set_okay(Treap* t) {
    if (!t) return;
    okay[rev[t->key]] = true;
    set_okay(t->lc);
    set_okay(t->rc);
}

int main () {
    srand(time(0));
    int n,m;
    scanf("%d%d",&n,&m);
    for (int i=1;i<=n;++i) {
        scanf("%lld",&w[i]);
    }
    vector<Edge> v;
    for (int i=1;i<=m;++i) {
        int x,y,z;
        scanf("%d%d%d",&x,&y,&z);
        v.push_back(Edge(x,y,z));
    }
    sort(v.begin(),v.end());
    djs.init();
    for (Edge &e:v) {
        if (djs.Find(e.a) == djs.Find(e.b)) continue;
        G[e.a].push_back(e.b);
        G[e.b].push_back(e.a);
        djs.Union(e.a,e.b);
        e.on_mst = true;
    }
    dfs(1,1);
    Treap* root = NULL;
    for (int i=1;i<=n;++i) {
        //cout << "pin = " << pin[i] << endl;
        p[ pin[i] ] = new Treap(pin[i],w[i]);
        p[ pout[i] ] = new Treap(pout[i],0);
    }
    for (int i=1;i<=2*n;++i) {
        root = merge(root,p[i]);
    }
    reverse(v.begin(),v.end());
    //is_anc(par,son)
    int ans=0;
    for (Edge e:v) {
        int x = e.a,y = e.b;
        if (is_anc(y,x)) swap(x,y);
        //x is parent, y is son
        if (okay[x] || okay[y]) continue;
        Treap* root = find_root(p[ pin[x] ]);
        //cout << "x = " << x << " , y = " << y << endl;
        //cout << "sum = " << root->sum << endl;
        if (root->sum >= e.c) {
            set_okay(root);
            continue;
        }
        ++ans;
        if (e.on_mst == true) {
            Treap *lc,*rc;
            //cout << "split = " << pin[y] <<" , " << pout[y] << endl;
            split(root,pin[y]-1,lc,root);
            split(root,pout[y],root,rc);
            Treap* t;
            t = merge(lc,rc);
            //root = merge(lc,rc);
        }
    }
    printf("%d\n",ans);
}



Measured memory_bytes: 35692