#include <fstream>
#include <vector>
#define nmax 32005
using namespace std;
vector<int> gf[nmax];
int n, M, P[nmax], D[nmax*2], Euler[nmax*2], Ord[nmax], arb[nmax<<4];
int A, B, rez, Nod, k, Max_sol=-1;
ifstream f("concurs.in");
ofstream g("concurs.out");
void citeste(){
f >> n >> M;
for(int i=1; i<=n; i++) f >> P[i];
for(int i=1; i<n; i++){
int x , y;
f >> x >> y;
gf[x].push_back(y);
}
}
void dfs(int nod, int niv){
++k;
D[k] = niv;
Euler[k] = nod;
Ord[nod] = k;
for(int i=0; i<gf[nod].size(); i++){
dfs(gf[nod][i], niv+1);
++k;
D[k] = niv;
Euler[k] = nod;
}
}
void udpate(int nod, int st, int dr, int poz, int val){
if (st == dr){
arb[nod] = st;
return ;
}
int mij = (st + dr) / 2;
if (poz <= mij) udpate(nod*2, st, mij, poz, val);
else udpate(nod*2+1, mij+1, dr, poz, val);
arb[nod] = arb[nod*2];
if(D[arb[nod]] > D[arb[nod*2+1]])
arb[nod] = arb[nod*2+1];
}
void query(int nod, int st, int dr, int a, int b){
if (a <= st && dr <= b){
if (D[arb[nod]] < rez){
rez = D[arb[nod]];
Nod = arb[nod];
// return ;
}
return;
}
int mij = (st + dr) / 2;
if (a <= mij) query(nod*2, st, mij, a, b);
if (b > mij) query(nod*2+1, mij+1, dr, a, b);
}
void rezolva(){
for(int i=1; i<=k; i++){
udpate(1, 1, k, i, i);
}
for(int i=1; i<=M; i++){
int x, y, X, Y;
f >> X >> Y;
x = Ord[X];
y = Ord[Y];
if (x > y){
int aux = x;
x = y;
y = aux;
}
rez = (1<<29);
query(1, 1, k, x, y);
if (Max_sol < P[Nod]){
Max_sol = P[Nod];
A = X;
B = Y;
}else if (Max_sol == P[Nod]){
if (A > X){
A = X;
B = Y;
}
}else if(Max_sol == P[Nod] && A == X && B > Y) B = Y;
}
}
void scrie(){
g << Max_sol << " " << A << " " << B << "\n";
}
int main(){
citeste();
dfs(1,1);
rezolva();
scrie();
f.close();
g.close();
return 0;
}