#include<iomanip>
#include<limits>
#include<thread>
#include<utility>
#include<iostream>
#include<string>
#include<algorithm>
#include<set>
#include<map>
#include<vector>
#include<stack>
#include<queue>
#include<cmath>
#include<numeric>
#include<cassert>
#include<random>
#include<chrono>
#include<unordered_map>
#include<fstream>
#include<list>
#include<functional>
#include<bitset>
#include<complex>
using namespace std;
typedef unsigned long long int ull;
typedef long long int ll;
typedef pair<ll,ll> pll;
typedef pair<int,int> pi;
typedef pair<double,double> pd;
typedef pair<double,ll> pdl;
#define F first
#define S second
const ll E=1e18+7;
const ll MOD=1000000007;




template<typename K,typename I,typename U>
struct LCT{
    K key;
    K left,right;
    function<bool(K,K)> Comp;
    
    const I I_E;
    const U U_E;
    I item,data;
    U up;
    const function<I(I,I)> F; //左、右
    const function<I(I,U,K,K,int)> G; //左、右,子の数
    const function<U(U,U)> H; //自分、親
    
    
    LCT* P;
    LCT* L;
    LCT* R;
    int children;
    
    
    LCT(const K &key,const function<bool(K,K)> &Comp,const I &I_E,const U &U_E,const function<I(I,I)> &F,const function<I(I,U,K,K,int)> &G,const function<U(U,U)> &H):key(key),left(key),right(right),Comp(Comp),I_E(I_E),U_E(U_E),item(I_E),data(I_E),up(U_E),F(F),G(G),H(H),P(NULL),L(NULL),R(NULL),children(1){}
    
    
    bool is_root() const {return P==NULL;}
    
    bool is_small_root() const {return P==NULL || (P->R!=this && P->L!=this);}
    
    void down(){
        item=G(item,up,key,key,1);
        if(L!=NULL){L->up=L->H(L->up,up); L->data=L->G(L->data,up,L->left,L->right,L->children);}
        if(R!=NULL){R->up=R->H(R->up,up); R->data=R->G(R->data,up,R->left,R->right,R->children);}
        up=U_E;
    }
    
    void RENEW(){
        children=1;
        if(L!=NULL){data=F(L->data,item); left=L->left; children+=L->children;}
        else{data=item; left=key;}
        if(R!=NULL){data=F(data,R->data); right=R->right; children+=R->children;}
        else{right=key;}
        data=G(data,up,left,right,children);
    }
    
    LCT* Rotate_R(){
        assert(L);
        down();
        L->down();
        
        LCT* ret=L;
        ret->P=P;
        if(P!=NULL && P->L==this){P->L=ret;}
        else if(P!=NULL && P->R==this){P->R=ret;}
        
        if(ret->R){L=ret->R; L->P=this;}
        else{L=NULL;}
        
        P=ret;
        ret->R=this;
        
        RENEW();
        ret->RENEW();
        
        return ret;
    }
    
    LCT* Rotate_L(){
        assert(R);
        down();
        R->down();
        
        LCT* ret=R;
        ret->P=P;
        if(P!=NULL && P->L==this){P->L=ret;}
        else if(P!=NULL && P->R==this){P->R=ret;}
        
        if(ret->L){R=ret->L; R->P=this;}
        else{R=NULL;}
        
        P=ret;
        ret->L=this;
        
        RENEW();
        ret->RENEW();
        
        return ret;
    }
    
    void Link(){
        Splay();
        while(!is_root()){
            P->Splay();
            P->down();
            P->R=this;
            P->RENEW();
            Splay();
        }
    }
    
    void Splay(){
        while(!is_small_root()){
            if(P->is_small_root()){
                if(P->L==this){P->Rotate_R();}
                else{P->Rotate_L();}
            }
            else{
                bool p1=(P->L==this);
                bool p2=(P->P->L==P);
                if(p1==p2){
                    if(p1){P->P->Rotate_R()->Rotate_R();}
                    else{P->P->Rotate_L()->Rotate_L();}
                }
                else{
                    if(p1){P->Rotate_R(); P->Rotate_L();}
                    else{P->Rotate_L(); P->Rotate_R();}
                }
            }
        }
    }
    
    LCT* expose(){
        Link();
        LCT* ret=R;
        R=NULL;
        RENEW();
        return ret;
    }
    
    LCT* min(){
        if(L==NULL){return this;}
        return L->min();
    }
    
    void update(const U &u){
        expose();
        up=H(up,u);
        data=G(data,u,left,right,children);
    }
    
    void small_tree_update(const U &u){
        Splay();
        up=H(up,u);
        data=G(data,u,left,right,children);
    }
    
    void node_update(const U &u){
        Splay();
        item=G(item,u,key,key,1);
        RENEW();
    }
};

vector<ll> uft;

ll parent(ll w){
    return (uft[w]==w?w:uft[w]=parent(uft[w]));
}

void merge(ll a,ll b){
    uft[parent(a)]=parent(b);
}

vector<pll> uft2;

ll parent2(ll w){
    return (uft2[w].F==w?w:uft2[w].F=parent2(uft2[w].F));
}

void merge2(ll a,ll b){
    if(parent2(a)==parent2(b)){return;}
    uft2[parent2(b)].S+=uft2[parent2(a)].S;
    uft2[parent2(a)].F=parent2(b);
}

vector<vector<ll>> EDGE;
vector<ll> P;

void dfs(ll w,ll p){
    P[w]=p;
    for(auto &I:EDGE[w]){
        if(I==p){continue;}
        dfs(I,w);
    }
}


int main(){
    ll n,m;
    cin>>n>>m;
    vector<ll> X(n);
    for(auto &I:X){cin>>I;}
    uft.resize(n);
    uft2.resize(n);
    for(int i=0;i<n;i++){uft[i]=uft2[i].F=i; uft2[i].S=X[i];}
    EDGE.resize(n);
    P.resize(n,-1);
    
    auto F=[](ll a,ll b){return a+b;};
    auto G=[](ll a,ll b,ll l,ll r,int children){return a+b*children;};
    auto H=[](ll a,ll b){return a+b;};
    vector<LCT<ll,ll,ll>> A(n,LCT<ll,ll,ll>(0,greater<ll>(),0,0,F,G,H));
    for(int i=0;i<n;i++){
        A[i].key=i;
        A[i].RENEW();
    }
    
    vector<pair<ll,pll>> edge(m);
    for(auto &I:edge){
        cin>>I.S.F>>I.S.S>>I.F;
        I.S.F--;
        I.S.S--;
    }
    sort(edge.begin(),edge.end());
    priority_queue<pll> Q;
    vector<bool> used(m,false);
    for(int i=0;i<m;i++){
        if(parent(edge[i].S.F)!=parent(edge[i].S.S)){
            used[i]=true;
            merge(edge[i].S.F,edge[i].S.S);
            EDGE[edge[i].S.F].push_back(edge[i].S.S);
            EDGE[edge[i].S.S].push_back(edge[i].S.F);
            Q.push({edge[i].F,i});
        }
    }
    dfs(0,-1);
    for(int i=1;i<n;i++){
        A[i].P=&A[P[i]];
    }
    for(int i=0;i<n;i++){
        A[i].update(X[i]);
    }
    ll ans=n-1;
    while(!Q.empty()){
        pll w=Q.top();
        Q.pop();
        if(P[edge[w.S].S.F]!=edge[w.S].S.S){
            swap(edge[w.S].S.F,edge[w.S].S.S);
        }
        assert(P[edge[w.S].S.F]==edge[w.S].S.S);
        A[edge[w.S].S.S].expose();
        auto p=A[edge[w.S].S.S].min();
        p->Splay();
        p->down();
        if(p->item<edge[w.S].F){
            A[edge[w.S].S.S].expose();
            A[edge[w.S].S.F].Splay();
            A[edge[w.S].S.F].down();
            A[edge[w.S].S.S].update(-A[edge[w.S].S.F].item);
            A[edge[w.S].S.F].P=NULL;
            ans--;
        }
        else{
            merge2(edge[w.S].S.S,edge[w.S].S.F);
        }
    }
    for(int i=0;i<m;i++){
        if(used[i]){continue;}
        if(parent2(edge[i].S.F)==parent2(edge[i].S.S) && uft2[parent2(edge[i].S.S)].S>=edge[i].F){ans++;}
    }
    cout<<m-ans<<endl;
    
    
    
    
    return 0;
}


Measured memory_bytes: 39664