#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const ll inf = (1ll << 60);
struct Mat {
ll a[5][5];
Mat() {
for (int i = 0; i < 5; ++i) {
for (int j = 0; j < 5; ++j) {
a[i][j] = -inf;
}
}
}
};
Mat id() {
Mat m;
for (int i = 0; i < 5; ++i)
m.a[i][i] = 0;
return m;
}
Mat operator*(const Mat &x, const Mat &y) {
Mat res;
for (int i = 0; i < 5; ++i) {
for (int j = 0; j < 5; ++j) {
for (int k = 0; k < 5; ++k) {
res.a[i][j] = max(res.a[i][j], x.a[i][k] + y.a[k][j]);
}
}
}
return res;
}
vector<int> c, p;
Mat single(int u) {
Mat m;
for (int b = 0; b < 5; ++b) {
if (b + 1 < 5)
m.a[b][b + 1] = c[u];
if (b - 1 >= 0)
m.a[b][b - 1] = p[u];
}
return m;
}
struct Node {
Mat fw, bw;
};
Node merge(const Node &L, const Node &R) { return {L.fw * R.fw, R.bw * L.bw}; }
struct Seg {
int n;
vector<Node> st;
vector<int> *rev;
Seg(int n, vector<int> &rev) : n(n), st(4 * n), rev(&rev) {}
Node neutral() {
Mat I = id();
return {I, I};
}
void build(int p, int l, int r) {
if (l == r) {
int u = (*rev)[l];
Mat m = single(u);
st[p] = {m, m};
return;
}
int m = (l + r) >> 1;
build(p << 1, l, m);
build(p << 1 | 1, m + 1, r);
st[p] = merge(st[p << 1], st[p << 1 | 1]);
}
Node qry(int p, int l, int r, int ql, int qr) {
if (ql > r || qr < l)
return neutral();
if (ql <= l && qr >= r)
return st[p];
int m = (l + r) >> 1;
Node L = qry(p << 1, l, m, ql, qr);
Node R = qry(p << 1 | 1, m + 1, r, ql, qr);
return merge(L, R);
}
};
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n, q;
cin >> n >> q;
c.resize(n);
p.resize(n);
for (int &i : c)
cin >> i;
for (int &i : p)
cin >> i;
vector<vector<int>> g(n);
for (int i = 1, u, v; i < n; ++i) {
cin >> u >> v, --u, --v;
g[u].push_back(v);
g[v].push_back(u);
}
vector<int> par(n, -1), depth(n), sz(n), heavy(n, -1), head(n), pos(n),
rev(n);
auto dfs1 = [&](auto &&self, int u, int p) -> void {
par[u] = p;
sz[u] = 1;
int best = 0;
for (int v : g[u]) {
if (v ^ p) {
depth[v] = depth[u] + 1;
self(self, v, u);
sz[u] += sz[v];
if (sz[v] > best) {
best = sz[v];
heavy[u] = v;
}
}
}
};
int timer = 0;
auto dfs2 = [&](auto &&self, int u, int h) -> void {
head[u] = h;
pos[u] = timer;
rev[timer] = u;
timer++;
if (~heavy[u]) {
self(self, heavy[u], h);
}
for (int v : g[u]) {
if (v == par[u] || v == heavy[u])
continue;
self(self, v, v);
}
};
dfs1(dfs1, 0, -1);
dfs2(dfs2, 0, 0);
Seg seg(n, rev);
seg.build(1, 0, n - 1);
auto qry_path = [&](int u, int v) -> Mat {
Mat left = id(), right = id();
while (head[u] != head[v]) {
if (depth[head[u]] > depth[head[v]]) {
Mat cur = seg.qry(1, 0, n - 1, pos[head[u]], pos[u]).bw;
left = left * cur;
u = par[head[u]];
} else {
Mat cur = seg.qry(1, 0, n - 1, pos[head[v]], pos[v]).fw;
right = cur * right;
v = par[head[v]];
}
}
if (depth[u] > depth[v]) {
Mat cur = seg.qry(1, 0, n - 1, pos[v], pos[u]).bw;
left = left * cur;
} else {
Mat cur = seg.qry(1, 0, n - 1, pos[u], pos[v]).fw;
right = cur * right;
}
return left * right;
};
while (q--) {
int u, v;
cin >> u >> v, --u, --v;
Mat tot = qry_path(u, v);
ll ans = -inf;
for (int j = 0; j < 5; ++j)
ans = max(ans, tot.a[2][j]);
cout << ans << "\n";
// vector<int> par(n, -1);
// queue<int> qu;
// qu.push(u);
// par[u] = u;
// while (qu.size()) {
// int x = qu.front();
// qu.pop();
// if (x == v)
// break;
// for (int to : g[x]) {
// if (!~par[to]) {
// par[to] = x;
// qu.push(to);
// }
// }
// }
//
// vector<int> path;
// int cur = v;
// for (; cur != u; cur = par[cur])
// path.push_back(cur);
// path.push_back(u);
// reverse(path.begin(), path.end());
// vector<ll> dp(5, -inf), ndp(5, -inf);
// dp[2] = 0;
// for (int x : path) {
// fill(ndp.begin(), ndp.end(), -inf);
// for (int b = 0; b < 5; ++b) {
// if (dp[b] == -inf)
// continue;
// if (b + 1 < 5) {
// ndp[b + 1] = max(ndp[b + 1], dp[b] + c[x]);
// }
// if (b - 1 >= 0) {
// ndp[b - 1] = max(ndp[b - 1], dp[b] + p[x]);
// }
// }
// dp.swap(ndp);
// }
// cout << ranges::max(dp) << "\n";
}
return 0;
}