#include <bits/stdc++.h>
using namespace std;
inline int in() {
  int32_t x;
  scanf("%d", &x);
  return x;
}
inline long long lin() {
  long long x;
  scanf("%lld", &x);
  return x;
}
inline string get() {
  char ch[2000010];
  scanf("%s", ch);
  return ch;
}
const int MAX_LG = 21;
const long long maxn = 1e5 + 10;
const long long maxm = 1e5 + 10;
const long long base = 29;
const long long mod = 1e9 + 7;
const long long INF = 1e9 + 100;
const long long SQ = 317;
long long f[maxn];
struct edge {
  long long v, u, weight;
  edge() {}
  edge(long long v, long long u, long long weight)
      : v(v), u(u), weight(weight) {}
} e[maxn];
struct query {
  long long v, u, l, id = -1;
  query() {}
  query(long long v, long long u, long long l, long long id)
      : v(v), u(u), l(l), id(id) {}
} Q[maxn];
vector<pair<long long, long long> > g[maxn];
long long sz[maxn];
long long head[maxn], heavy[maxn], h[maxn], pre[maxn], n, q, cur,
    tree_pos[maxn], edge_pos[maxn], root[maxn][MAX_LG];
struct node {
  long long ret, pref, suf, bitCnt = 0;
  node() {}
  node(long long ret, long long pref, long long suf, long long bitCnt)
      : ret(ret), pref(pref), suf(suf), bitCnt(bitCnt) {}
} stree[4 * maxn];
inline void getsz(long long v, long long pr = 0) {
  sz[v] = 1;
  long long maxi = -1;
  for (long long i = 1; i < MAX_LG; i++)
    root[v][i] = root[root[v][i - 1]][i - 1];
  for (auto u : g[v])
    if (u.first - pr) {
      h[u.first] = root[u.first][0] = v, h[u.first] = h[v] + 1,
      pre[u.first] = v, getsz(u.first, v), sz[v] += sz[u.first];
      if (sz[u.first] > maxi) maxi = sz[u.first], heavy[v] = u.first;
    }
}
inline long long lca(long long p, long long q) {
  if (h[p] < h[q]) swap(p, q);
  for (long long i = MAX_LG - 1; i >= 0; i--)
    if (h[p] - (1 << i) >= h[q]) p = root[p][i];
  if (p == q) return p;
  for (long long i = MAX_LG - 1; i >= 0; i--)
    if (root[p][i] != root[q][i]) p = root[p][i], q = root[q][i];
  return root[p][0];
}
inline node merge(node &L, node &R) {
  long long rt = L.ret + R.ret;
  if (L.suf && R.pref) {
    rt -= f[L.suf] + f[R.pref];
    rt += f[L.suf + R.pref];
  }
  node ret;
  ret = {rt, L.pref + bool(L.pref == L.bitCnt) * R.pref,
         R.suf + bool(R.suf == R.bitCnt) * L.suf, L.bitCnt + R.bitCnt};
  return ret;
}
inline void update(long long qx, long long p = 0, long long l = 0,
                   long long r = cur - 1) {
  if (l > qx || r < qx || r < l) return;
  if (l == r) {
    stree[p] = {f[1], 1, 1, 1};
    return;
  }
  long long mid = (l + r) >> 1;
  update(qx, 2 * p + 1, l, mid);
  update(qx, 2 * p + 2, mid + 1, r);
  stree[p] = merge(stree[2 * p + 1], stree[2 * p + 2]);
}
inline node get(long long ql, long long qr, long long p = 0, long long l = 0,
                long long r = cur - 1) {
  if (l > qr || r < ql || r < l) return {0, 0, 0, 0};
  if (l >= ql && r <= qr) return stree[p];
  long long mid = (l + r) >> 1;
  node Left = get(ql, qr, 2 * p + 1, l, mid),
       Right = get(ql, qr, 2 * p + 2, mid + 1, r);
  return merge(Left, Right);
}
inline void build(long long p = 0, long long l = 0, long long r = cur - 1) {
  if (l == r) {
    stree[p] = {0, 0, 0, 1};
    return;
  }
  long long mid = (l + r) >> 1;
  build(2 * p + 1, l, mid), build(2 * p + 2, mid + 1, r);
  stree[p] = {0, 0, 0, r - l + 1};
}
long long res[maxn];
inline node get_direct_path(long long v, long long LCA) {
  node ret = {0, 0, 0, 0};
  while (head[v] != head[LCA]) {
    node Left = get(tree_pos[head[v]], tree_pos[v]);
    ret = merge(Left, ret);
    v = pre[head[v]];
  }
  node Left = get(tree_pos[LCA] + 1, tree_pos[v]);
  ret = merge(Left, ret);
  return ret;
}
inline long long get_path(long long v, long long u) {
  long long LCA = lca(v, u);
  node Left = get_direct_path(v, LCA);
  node Right = get_direct_path(u, LCA);
  swap(Left.suf, Left.pref);
  return merge(Left, Right).ret;
}
int32_t main() {
  memset(pre, -1, sizeof pre);
  memset(heavy, -1, sizeof heavy);
  n = in(), q = in();
  for (long long i = 1; i <= n - 1; i++) f[i] = in();
  for (long long i = 0; i < n - 1; i++) {
    e[i] = {in() - 1, in() - 1, in()};
    g[e[i].v].push_back({e[i].u, e[i].weight});
    g[e[i].u].push_back({e[i].v, e[i].weight});
  }
  sort(e, e + n - 1,
       [](const edge &a, const edge &b) { return a.weight > b.weight; });
  for (long long i = 0; i < q; i++) Q[i] = {in() - 1, in() - 1, in(), i};
  sort(Q, Q + q, [](const query &a, const query &b) { return a.l > b.l; });
  getsz(0);
  for (long long i = 0; i < n - 1; i++)
    if (h[e[i].v] > h[e[i].u]) swap(e[i].v, e[i].u);
  for (long long i = 0; i < n; i++) {
    if (pre[i] == -1 || heavy[pre[i]] != i)
      for (long long u = i; u != -1; u = heavy[u])
        head[u] = i, tree_pos[u] = cur++;
  }
  build();
  for (long long i = 0; i < n - 1; i++) edge_pos[i] = tree_pos[e[i].u];
  long long l = 0;
  for (long long i = 0; i < q; i++) {
    while (l < n - 1 && e[l].weight >= Q[i].l) update(edge_pos[l++]);
    res[Q[i].id] = get_path(Q[i].v, Q[i].u);
  }
  for (long long i = 0; i < q; i++, cout << "\n") cout << res[i];
  return 0;
}
