#include <bits/stdc++.h>
#define ll long long int
#define ld long double
#define ull unsigned long long int
#define forn(i,n)for(ll i=0;i<(n);i++)
#define forn_rev(i,n)for(ll i=(n)-1;i>=0;i--)
#define for1n(i,n) for(ll i=1;i<=(n);i++)
#define ARRAY_SIZE(a) sizeof(a)/sizeof(*a)
#define MOD 1000000007
#define MAXN 100005

using namespace std;

vector<ll> adj[MAXN];
bool visited[MAXN],good[MAXN];
void dfs(ll s,vector<ll> &h){
    if(!visited[s]){
        visited[s]=1;
        forn(i,adj[s].size()){

                if(h[s]>h[adj[s][i]]){
                    good[adj[s][i]]=0;
                    visited[adj[s][i]]=1;
                }
                else{
                    if(h[s]==h[adj[s][i]]){
                        good[s]=good[adj[s][i]]=0;
                        visited[adj[s][i]]=1;
                    }
                    else if(h[s]<h[adj[s][i]]){
                        good[s]=0;


                    }

                }

        }
    }

}


int main()
{
    ios_base::sync_with_stdio(0);
    cin.tie(NULL);cout.tie(NULL);
    memset(visited,0,sizeof visited);
    memset(good,1,sizeof good);
    ll T=1;
    //cin>>T;
    while(T--)
    {
        ll N,M;
        cin>>N>>M;
        vector<ll> h(N);
        forn(i,N) cin>>h[i];
        forn(i,M){
            ll a,b;
            cin>>a>>b;
            adj[a-1].push_back(b-1);
            adj[b-1].push_back(a-1);
        }
        forn(i,N){
            if(!visited[i]){
                dfs(i,h);//cout<<i<<endl;
            }
        }
        ll ans=0;
        forn(i,N) {//cout<<good[i]<<" ";
        if(good[i]) ans++;}
        cout<<ans;










    }



    return 0;
}


/*


struct data{

    ll count,index;

};

vector<ll> arr(10000);
vector<data> tmax(4*MAXN);



auto combine(data a,data b){
    //ultra based combine function for easier understanding
    data res=0;
    if(a>0) res.count++;
    if(b>0) res.count++
    return res;
}



void build(ll v,ll tl,ll tr)
{
    if(tl==tr)
    {

        tmax[v]=arr[tl];
        //leaf nodes
    }
    else
    {
        //store in array. Thus childs are 2*v and 2*v+1
        ll tm=(tl+tr)/2;//mid point
        build(2*v,tl,tm);//recurse to left sub tree
        build(2*v+1,tm+1,tr);//recurse to right tree
        tmax[v]=combine(tmax[2*v],tmax[2*v+1]);
    }
}

auto getmax(ll v,ll tl,ll tr,ll l,ll r)
{
    if(r<tl || l>tr)
        return -1;//check if outside range
    if(l<=tl && tr<=r)
        return tmax[v];//in range then return that value

    ll tm=(tl+tr)/2;
    //recurse to left and right subtree
    ll left=getmax(2*v,tl,tm,l,r),right=getmax(2*v+1,tm+1,tr,l,r);
    return combine(left,right);
}

ll update(ll v,ll tl,ll tr,ll l,ll tr,ll val){
    if(l>r) return;
    if(l==tl && tr==r){
        if(tmax[v]>=0)
            tmax[v]+=val;//update tree leaves here
        else return -1;

    }
    else{
        ll tm=(tl+tr)/2;
        if(tl>=m)
        ll right=update(2*v+1,tm+1,tr,val);//recurse to right subtree
        if(right==-1) return -1;
        update(2*v,tl,tm,val);//recurse to left subtree

        tmax[v]=combine(tmax[2*v],tmax[2*v+1]);//combine

    }

}
void pointupdate(ll v,ll tl,ll tr,ll pos,ll val){

    if(tl==tr){
        tmax[v]=make_data(val);//update tree leaves here

    }
    else{
        ll tm=(tl+tr)/2;
        if(pos<=tm) update(2*v,tl,tm,val);//recurse to left subtree
        else update(2*v+1,tm+1,tr,val);//recurse to right subtree

        tmax[v]=combine(tmax[2*v],tmax[2*v+1]);//combine

    }

}


*/





/*


struct data{

    ll count,index;

};

vector<ll> arr(10000);
vector<data> tmax(4*MAXN);



auto combine(data a,data b){
    //ultra based combine function for easier understanding
    data res=0;
    if(a>0) res.count++;
    if(b>0) res.count++
    return res;
}



void build(ll v,ll tl,ll tr)
{
    if(tl==tr)
    {

        tmax[v]=arr[tl];
        //leaf nodes
    }
    else
    {
        //store in array. Thus childs are 2*v and 2*v+1
        ll tm=(tl+tr)/2;//mid point
        build(2*v,tl,tm);//recurse to left sub tree
        build(2*v+1,tm+1,tr);//recurse to right tree
        tmax[v]=combine(tmax[2*v],tmax[2*v+1]);
    }
}

auto getmax(ll v,ll tl,ll tr,ll l,ll r)
{
    if(r<tl || l>tr)
        return -1;//check if outside range
    if(l<=tl && tr<=r)
        return tmax[v];//in range then return that value

    ll tm=(tl+tr)/2;
    //recurse to left and right subtree
    ll left=getmax(2*v,tl,tm,l,r),right=getmax(2*v+1,tm+1,tr,l,r);
    return combine(left,right);
}

ll update(ll v,ll tl,ll tr,ll l,ll tr,ll val){
    if(l>r) return;
    if(l==tl && tr==r){
        if(tmax[v]>=0)
            tmax[v]+=val;//update tree leaves here
        else return -1;

    }
    else{
        ll tm=(tl+tr)/2;
        if(tl>=m)
        ll right=update(2*v+1,tm+1,tr,val);//recurse to right subtree
        if(right==-1) return -1;
        update(2*v,tl,tm,val);//recurse to left subtree

        tmax[v]=combine(tmax[2*v],tmax[2*v+1]);//combine

    }

}
void pointupdate(ll v,ll tl,ll tr,ll pos,ll val){

    if(tl==tr){
        tmax[v]=make_data(val);//update tree leaves here

    }
    else{
        ll tm=(tl+tr)/2;
        if(pos<=tm) update(2*v,tl,tm,val);//recurse to left subtree
        else update(2*v+1,tm+1,tr,val);//recurse to right subtree

        tmax[v]=combine(tmax[2*v],tmax[2*v+1]);//combine

    }

}


*/





Measured memory_bytes: 10060