#include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; i < (n); i++)
using namespace std;
using ll = long long;
const int INF = (1<<30)-1;
const long long LINF = (1LL<<62)-1;
const int dx[] = {-1, 0, 1, 0};
const int dy[] = {0, 1, 0, -1};
template<class T> inline bool chmax(T& a, T b) { if (a < b) { a = b; return true; } return false; }
template<class T> inline bool chmin(T& a, T b) { if (a > b) { a = b; return true; } return false; }

class LCA {
  vector<vector<int>> par;
  vector<int> dep;
  void dfs(int cur, int prev, vector<vector<int>> &to) {
    if (prev < 0)
      dep[cur] = 0;
    else {
      par[cur][0] = prev;
      dep[cur] = dep[prev] + 1;
    }
    for (auto next : to[cur]) {
      if (next == prev)
        continue;
      dfs(next, cur, to);
    }
  }
public:
  LCA(vector<vector<int>> &to, int root = 0) {
    int n = to.size(), lg = 1;
    while (1 << lg < n) lg++;
    par.resize(n, vector<int>(lg, -1));
    dep.resize(n);
    dfs(root, -1, to);
    for (int i = 1; i < lg; i++) {
      for (int j = 0; j < n; j++) {
        if (par[j][i - 1] < 0)
          par[j][i] = -1;
        else
          par[j][i] = par[par[j][i - 1]][i - 1];
      }
    }
  }
  int query(int x, int y) {
    if (dep[x] < dep[y]) swap(x, y);
    int diff = dep[x] - dep[y], lg = par[x].size();
    for (int i = 0; i < lg; i++) {
      if (diff >> i & 1)
        x = par[x][i];
    }
    if (x == y) return x;
    for (int i = lg - 1; i >= 0; i--) {
      if (par[x][i] != par[y][i]) {
        x = par[x][i];
        y = par[y][i];
      }
    }
    return par[x][0];
  }
};

vector<vector<int>> to, co, id;
vector<vector<tuple<int, bool, int, int>>> node;
vector<ll> ans;

struct Color {
  ll c_sum = 0;
  int c_num = 0;
};

void dfs(int now, int prev, ll sum, map<int, Color> &nowdata) {
  for (auto query : node[now]) {
    int q_id, q_col, q_cost;
    bool flag;
    tie(q_id, flag, q_col, q_cost) = query;
    if (flag)
      ans[q_id] += sum-nowdata[q_col].c_sum+nowdata[q_col].c_num*q_cost;
    else
      ans[q_id] -= (sum-nowdata[q_col].c_sum+nowdata[q_col].c_num*q_cost)*2;
  }
  for (int i = 0; i < to[now].size(); i++) {
    if (to[now][i] == prev)
      continue;
    sum += co[now][i];
    nowdata[id[now][i]].c_sum += co[now][i];
    nowdata[id[now][i]].c_num++;
    dfs(to[now][i], now, sum, nowdata);
    sum -= co[now][i];
    nowdata[id[now][i]].c_sum -= co[now][i];
    nowdata[id[now][i]].c_num--;
  }
}

signed main() {
  ios::sync_with_stdio(false);
  cin.tie(0);
  int n, q;
  cin >> n >> q;
  to.resize(n);
  co.resize(n);
  id.resize(n);
  rep(i, n-1) {
    int a, b, c, d;
    cin >> a >> b >> c >> d;
    --a, --b, --c;
    to[a].push_back(b);
    co[a].push_back(d);
    id[a].push_back(c);
    to[b].push_back(a);
    co[b].push_back(d);
    id[b].push_back(c);
  }
  node.resize(n);
  LCA lca(to);
  rep(i, q) {
    int c, d, x, y;
    cin >> c >> d >> x >> y;
    --c, --x, --y;
    node[x].push_back(make_tuple(i, true, c, d));
    node[y].push_back(make_tuple(i, true, c, d));
    node[lca.query(x, y)].push_back(make_tuple(i, false, c, d));
  }
  ans.resize(q, 0);
  map<int, Color> mp;
  dfs(0, -1, 0, mp);
  rep(i, q)
    cout << ans[i] << '\n';
  return 0;
}

Measured memory_bytes: 50932