#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace std;
using namespace __gnu_pbds;
template<typename T>
using ordered_set = tree<T, null_type, less_equal<T>, rb_tree_tag, tree_order_statistics_node_update>;
#define int long long
signed main() {
ios::sync_with_stdio(0);
cin.tie(0);
#ifdef CB
freopen("be2.txt","r",stdin);
// freopen("out.txt","w",stdout);
#endif
int N,M;
cin>>N>>M;
vector<int>v(N+1);
int su=0;
for(int i=1;i<=N;i++){
cin>>v[i];
su+=v[i];
}
vector<vector<int>>g(N+1);
for(int i=0;i<M;i++){
int a,b;
cin>>a>>b;
g[a].push_back(b);
g[b].push_back(a);
}
int ans=INT_MAX;
int ans2=0;
vector<int>l(N+1,INT_MAX),a(N+1,0);
vector<int>s(N+1);
vector<ordered_set<int>>z(N+1);
auto dfs=[&](auto self,int i)->void{
for(int j:g[i]){
if(l[j]==l[i]-1){
continue;
}
if(l[j]!=INT_MAX){
if(l[j]<l[a[i]]){
a[i]=j;
}
continue;
}
l[j]=l[i]+1;
self(self,j);
if(l[a[j]]<l[a[i]]){
a[i]=a[j];
}
if(l[a[j]]>l[i]){
z[i].insert(s[j]);
int s1=su-s[j],s2,s3;
// auto it=z[j].upper_bound(s[j]/2);
// if(it!=z[j].end()){
// s2=*it;
// s3=su-s1-s2;
// ans=min(ans,max({s1,s2,s3})-min({s1,s2,s3}));
// }
// if(it!=z[j].begin()){
// --it;
// s2=*it;
// s3=su-s1-s2;
// ans=min(ans,max({s1,s2,s3})-min({s1,s2,s3}));
// }
// if(!z[j].empty()){
// s2=*s.begin();
// s3=su-s1-s2;
// ans=min(ans,max({s1,s2,s3})-min({s1,s2,s3}));
// s2=*--s.end();
// s3=su-s1-s2;
// ans=min(ans,max({s1,s2,s3})-min({s1,s2,s3}));
// }
for(int s2:z[j]){
s3=su-s1-s2;
if(ans>max({s1,s2,s3})-min({s1,s2,s3})){
ans=max({s1,s2,s3})-min({s1,s2,s3});
ans2=0;
}
if(ans==max({s1,s2,s3})-min({s1,s2,s3})){
ans2++;
}
}
}
s[i]+=s[j];
if(z[j].size()>z[i].size()){
swap(z[i],z[j]);
}
for(int k:z[j]){
z[i].insert(k);
}
}
s[i]+=v[i];
};
l[1]=0;
dfs(dfs,1);
// for(int i=1;i<=N;i++){
// cout<<i<<" : "<<l[i]<<" "<<a[i]<<" "<<s[i]<<endl;
// }
cout<<ans<<'\n';
cout<<ans2<<'\n';
return 0;
}