rt
#include<bits/stdc++.h>
#define int long long
#define pb push_back
using namespace std;
vector<int>g[400005],newg[400005];
int K[500005],n,m,pos[500005],maxblock[500005],sumblock[500005],dep,cur,dpmax[500005],dpsum[500005];
int dfn[500005],low[500005];
int deg[500005];
bool vis[500005];
stack<int>stk;
struct node{
int u,v;
}edge[500005];
namespace gghack{
void tarjan(int now){
dfn[now] = low[now] = ++dep;
stk.push(now);
vis[now] = 1;
for(auto x : g[now]){
if(!dfn[x]){
tarjan(x);
low[now] = min(low[x],low[now]);//前向边
}
else if(vis[x])low[now] = min(low[x],dfn[now]);//返祖边
//横插边不在子树中,同时没有被标记,不用管
}
if(dfn[now] == low[now]){
++cur;
while(stk.top()!=now){
int noww = stk.top();
stk.pop();
vis[noww] = 0;
maxblock[cur] = max(maxblock[cur],K[noww]);
sumblock[cur] += K[noww];
pos[noww] = cur;
}
stk.pop();
vis[now] = 0;
maxblock[cur] = max(maxblock[cur],K[now]);
sumblock[cur] += K[now];
pos[now] = cur;
}
return ;
}
void topo(){
queue<int>q;
for(int i = 1;i <= cur;++i){dpsum[i] = sumblock[i],dpmax[i] = maxblock[i];if(!deg[i])q.push(i);}
while(!q.empty()){
int now = q.front();
q.pop();
for(auto x : newg[now]){
if(dpsum[now] + sumblock[x] > dpsum[x])dpmax[x] = 0,dpmax[x] = max(dpmax[now],maxblock[x]),dpsum[x] = dpsum[now] + sumblock[x];
else if(dpsum[now] + sumblock[x] == dpsum[x])dpmax[x] = max(dpmax[now],dpmax[x]);
deg[x]--;
if(!deg[x])q.push(x);
}
}
for(int i = 1;i <= cur;++i){
if(dpsum[0] < dpsum[i]){
dpsum[0] = dpsum[i];
dpmax[0] = 0;
dpmax[0] = maxblock[i];
}
else if(dpsum[0] == dpsum[i])dpmax[0] = max(maxblock[i],dpmax[0]);
}
cout << dpsum[0] << " " << dpmax[0] << '\n';
return ;
}
void main(){
ios::sync_with_stdio(false);
cin.tie(0);
cin >> n >> m;
int u,v;
for(int i = 1;i <= n;++i)cin >> K[i];
for(int i = 1;i <= m;++i){
cin >> u >> v;
g[u].pb(v);
edge[i].u = u,edge[i].v = v;
}
for(int i = 1;i <= n;++i)if(!dfn[i])tarjan(i);
for(int i = 1;i <= m;++i){
int ru = pos[edge[i].u],rv = pos[edge[i].v];
if(ru == rv)continue;
newg[ru].pb(rv);
deg[rv]++;
}
topo();
return ;
}
}
signed main(){gghack::main();}