#include <stdio.h>
#include <stdbool.h>

int *to, *nxt, *head;  // global adjacency arrays
int idx;

static inline int find(int x, int p[]) { // DSU find with path compression
    while (x != p[x]) x = p[x] = p[p[x]];
    return x;
}

void add(int u,int v){                   // add edge
    to[++idx]=v;
    nxt[idx]=head[u];
    head[u]=idx;
}

int main(void){
    int n,m; 
    scanf("%d%d",&n,&m);
    char s[n+1]; 
    scanf("%s",s+1);

    // allocate arrays on stack (VLA)
    int p[n+1], sz[n+1], head_arr[n+2], to_arr[2*m+2], nxt_arr[2*m+2];
    bool occ[n+1], seen[n+1];

    // bind global pointers to local arrays
    to = to_arr; nxt = nxt_arr; head = head_arr;

    // initialize
    for(int i=1;i<=n;i++){occ[i]=s[i]=='1';p[i]=i;sz[i]=1;head[i]=0;seen[i]=0;}

    // build adjacency & union occupied cities
    for(int i=0,u,v;i<m;i++){
        scanf("%d%d",&u,&v);
        add(u,v); add(v,u);
        if(occ[u]&&occ[v]){
            int a=find(u,p), b=find(v,p);
            if(a!=b){
                if(sz[a]<sz[b]){int t=a;a=b;b=t;}
                p[b]=a; sz[a]+=sz[b];
            }
        }
    }

    long base=0;
    for(int i=1;i<=n;i++)               // initial profit
        if(occ[i]&&find(i,p)==i)
            base+=1LL*sz[i]*(sz[i]-1)/2;

    long best=base; int city=1;

    // evaluate each unoccupied city
    for(int u=1;u<=n;u++) if(!occ[u]){
        long loss=0,sum=1;
        for(int e=head[u];e;e=nxt[e]){  // scan neighbors
            int v=to[e]; if(!occ[v]) continue;
            int r=find(v,p);
            if(!seen[r]){               // avoid duplicate comps
                seen[r]=1;
                loss+=1LL*sz[r]*(sz[r]-1)/2;
                sum+=sz[r];
            }
        }
        long newp=base-loss+1LL*sum*(sum-1)/2;
        if(newp>best||(newp==best&&u<city)) best=newp,city=u;
        for(int e=head[u];e;e=nxt[e]){int v=to[e];if(occ[v])seen[find(v,p)]=0;} // reset flags
    }

    printf("%d %lld\n",city,best);
    return 0;
}