#include <bits/stdc++.h>
using namespace std;
const int Inf = 0x3f3f3f3f;
const int maxn = 2000 + 10;
inline int R_int() {
  register int n = 0;
  register char ch = getchar();
  while (ch < '0' || ch > '9') ch = getchar();
  while (ch >= '0' && ch <= '9')
    n = (n << 1) + (n << 3) + (ch ^ '0'), ch = getchar();
  return n;
}
int Que_count;
int EE[maxn];
struct Edge {
  int to, next;
  int cap, flow, Dist;
  Edge() {}
  Edge(int to, int next, int cap, int Dist) {
    this->to = to;
    this->flow = 0;
    this->cap = cap;
    this->Dist = Dist;
    this->next = next;
  }
};
Edge edges[maxn * maxn << 1];
int Dist[maxn];
bool vis[maxn];
int bz[maxn];
int G[maxn];
int tot = 0;
int S, T;
int num;
int n;
queue<int> Q;
inline void Init() {
  tot = -1;
  memset(G, -1, sizeof(G));
}
inline void AddEdge(int from, int to, int cap, int Dist) {
  edges[++tot] = Edge(to, G[from], cap, Dist);
  G[from] = tot;
  edges[++tot] = Edge(from, G[to], 0, -Dist);
  G[to] = tot;
}
inline bool Spfa() {
  memset(vis, 0, sizeof(vis));
  memset(Dist, 0x3f, sizeof(Dist));
  Dist[S] = 0;
  vis[S] = 1;
  Q.push(S);
  while (!Q.empty()) {
    int u = Q.front();
    Q.pop();
    vis[u] = 0;
    for (int i = G[u]; ~i; i = edges[i].next) {
      int t = edges[i].to;
      if ((Dist[t] > Dist[u] + edges[i].Dist) && edges[i].cap > edges[i].flow) {
        Dist[t] = Dist[u] + edges[i].Dist;
        if (!vis[t]) vis[t] = 1, Q.push(t);
      }
    }
  }
  return Dist[T] != Dist[T + 1];
}
inline int Dfs(int u, int rest) {
  if (u == T || rest == 0) return rest;
  int flow = 0, r = 0;
  vis[u] = 1;
  for (int i = G[u]; ~i; i = edges[i].next) {
    int t = edges[i].to;
    if ((!vis[t]) && edges[i].cap > edges[i].flow &&
        Dist[t] == Dist[u] + edges[i].Dist) {
      r = Dfs(t, min(rest, edges[i].cap - edges[i].flow));
      edges[i].flow += r;
      edges[i ^ 1].flow -= r;
      flow += r;
      rest -= r;
      if (rest == 0) break;
    }
  }
  return flow;
}
inline void Dinic() {
  int ans = 0, flow = 0;
  while (Spfa()) {
    int r = Dfs(S, Inf);
    flow += r;
    ans += r * Dist[T];
  }
  ans = -ans;
  if (flow != Que_count)
    puts("-1");
  else
    printf("%d\n", ans);
}
struct Tree {
  struct Edge {
    int to, next;
    Edge() {}
    Edge(int to, int next) {
      this->to = to;
      this->next = next;
    }
  };
  Edge edges[maxn << 1];
  bool tag[maxn];
  int size[maxn];
  int prt[maxn];
  int Dfn[maxn];
  int pos[maxn];
  int Idx[maxn];
  int G[maxn];
  int Time;
  int tot;
  int rt;
  int H;
  int n;
  inline void Init(int n) {
    this->n = n;
    rt = R_int();
  }
  inline void AddEdge(int from, int to) {
    edges[++tot] = Edge(to, G[from]);
    G[from] = tot;
  }
  inline void Dfs(int u, int fa) {
    prt[u] = fa;
    Dfn[u] = ++Time;
    pos[Time] = u;
    for (int i = G[u]; i != 0; i = edges[i].next) {
      int t = edges[i].to;
      if (t ^ fa) Dfs(t, u);
    }
  }
  inline void Read_Tree() {
    for (int i = 2; i <= n; i++) {
      int x = R_int(), y = R_int();
      AddEdge(x, y);
      AddEdge(y, x);
    }
    Dfs(rt, -1);
  }
  inline void Modify(bool left) {
    int m = R_int();
    for (int i = 1; i <= m; i++) {
      int x = R_int(), c = R_int();
      tag[x] = 1;
      Idx[x] = ++num;
      size[x] = c;
      if (x == rt) H = c;
    }
    for (int i = Time; i >= 1; i--) {
      int x = pos[i], v = pos[i];
      bool Is = 1;
      while (~x) {
        if (tag[x] && Is) {
          if (EE[v] == -1)
            EE[v] = Idx[x];
          else
            ::AddEdge(EE[v], Idx[x], 1, -bz[v]);
          Is = 0;
        } else if (tag[x] && tag[v])
          size[x] -= size[v];
        x = prt[x];
      }
    }
    for (int i = 1; i <= n; i++) {
      if (tag[i]) {
        Que_count += size[i];
        if (left)
          ::AddEdge(S, Idx[i], size[i], 0);
        else
          ::AddEdge(Idx[i], T, size[i], 0);
      }
    }
  }
};
Tree Tr[2];
int col;
signed main() {
  memset(EE, -1, sizeof(EE));
  n = R_int();
  Init();
  Tr[0].Init(n);
  Tr[1].Init(n);
  for (int i = 1; i <= n; i++) bz[i] = R_int();
  num = 0;
  S = 0;
  T = 1005;
  Tr[0].Read_Tree();
  Tr[1].Read_Tree();
  Tr[0].Modify(1);
  Tr[1].Modify(0);
  Que_count >>= 1;
  if (Tr[0].H != Tr[1].H) return (!printf("-1\n"));
  for (int i = 1; i <= n; i++) {
    if (Tr[0].size[i] < 0 || Tr[1].size[i] < 0) return (!printf("-1\n"));
  }
  Dinic();
  return 0;
}
