$$n,k\le 2000$$

$$S$$（或$$T$$）中每次取出$$w_x$$最小的$$x$$，如果从$$x$$跳到$$f_x$$没有超过上限，那就跳过去。由于总和减小，这样操作一定会利于后面的操作，于是一定能到达最低点。

using namespace std;
#include <bits/stdc++.h>
#define N 2005
#define ll long long
#define INF 10000000000000
#define fi first
#define se second
#define mp(x,y) make_pair(x,y)
int n,K;
int h[N];
struct EDGE{
int to;
EDGE *las;
} e[N*2];
int ne;
EDGE *last[N];
void link(int u,int v){
e[ne]={v,last[u]};
last[u]=e+ne++;
}
int s[N],t[N];
ll mx[N];
int to[N];
ll w[N];
void dfs(int x,int fa,ll s){
mx[x]=max(mx[fa],s);
for (EDGE *ei=last[x];ei;ei=ei->las)
if (ei->to!=fa)
dfs(ei->to,x,s+h[ei->to]-h[x]);
}
priority_queue<pair<ll,int>,vector<pair<ll,int> >,greater<pair<ll,int> > > qs,qt;
int main(){
//	freopen("in.txt","r",stdin);
scanf("%d",&n);
for (int i=1;i<=n;++i)
scanf("%d",&h[i]);
for (int i=1;i<n;++i){
int u,v;
scanf("%d%d",&u,&v);
}
scanf("%d",&K);
for (int i=1;i<=K;++i)
scanf("%d%d",&s[i],&t[i]);
mx[0]=-INF;
for (int i=1;i<=n;++i){
dfs(i,0,0);
for (int j=1;j<=n;++j)
if (h[j]<h[i] || h[j]==h[i] && j<i){
if (to[i]==0 || mx[to[i]]>mx[j])
to[i]=j,w[i]=mx[j];
}
}
int cnt=0;
ll S=0,T=0,ans=0;
for (int i=1;i<=K;++i){
S+=h[s[i]],T+=h[t[i]];
if (to[s[i]]) qs.push(mp(w[s[i]],i));
if (to[t[i]]) qt.push(mp(w[t[i]],i));
cnt+=(s[i]!=t[i]);
}
ans=max(S,T);
while (cnt>0/* && (!qs.empty() || !qt.empty())*/){
if (qt.empty() || !qs.empty() && S+qs.top().fi<T+qt.top().fi){
int x=qs.top().se;
qs.pop();
ans=max(ans,S+w[s[x]]);
cnt-=(s[x]!=t[x]);
S-=h[s[x]];
s[x]=to[s[x]];
S+=h[s[x]];
cnt+=(s[x]!=t[x]);
if (to[s[x]])
qs.push(mp(w[s[x]],x));
}
else{
int x=qt.top().se;
qt.pop();
ans=max(ans,T+w[t[x]]);
cnt-=(s[x]!=t[x]);
T-=h[t[x]];
t[x]=to[t[x]];
T+=h[t[x]];
cnt+=(s[x]!=t[x]);
if (to[t[x]])
qt.push(mp(w[t[x]],x));
}
}
printf("%lld\n",ans);
return 0;
}