#include <bits/stdc++.h>
using namespace std;
int LOG = 20;
struct lowest_common_ancestor{
  vector<int> d;
  vector<vector<int>> p;
  lowest_common_ancestor(){
  }
  lowest_common_ancestor(vector<vector<int>> &ch){
    int N = ch.size();
    d = vector<int>(N, 0);
    p = vector<vector<int>>(LOG, vector<int>(N, -1));
    queue<int> Q;
    Q.push(0);
    while (!Q.empty()){
      int v = Q.front();
      Q.pop();
      for (int w : ch[v]){
        d[w] = d[v] + 1;
        p[0][w] = v;
        Q.push(w);
      }
    }
    for (int i = 1; i < LOG; i++){
      for (int j = 0; j < N; j++){
        if (p[i - 1][j] != -1){
          p[i][j] = p[i - 1][p[i - 1][j]];
        }
      }
    }
  }
  int lca(int v, int w){
    if (d[v] < d[w]){
      swap(v, w);
    }
    int diff = d[v] - d[w];
    for (int i = 0; i < LOG; i++){
      if (diff >> i & 1){
        v = p[i][v];
      }
    }
    if (v == w){
      return v;
    } else {
      for (int i = LOG - 1; i >= 0; i--){
        if (p[i][v] != p[i][w]){
          v = p[i][v];
          w = p[i][w];
        }
      }
      return p[0][v];
    }
  }
};
template <typename T>
struct segment_tree{
  int N;
  vector<T> ST;
  T E;
  segment_tree(){
  }
  segment_tree(vector<T> A, T E): E(E){
    int n = A.size();
    N = 1;
    while (N < n){
      N *= 2;
    }
    ST = vector<T>(N * 2 - 1, E);
    for (int i = 0; i < n; i++){
      ST[N - 1 + i] = A[i];
    }
    for (int i = N - 2; i >= 0; i--){
      ST[i] = ST[i * 2 + 1] + ST[i * 2 + 2];
    }
  }
  void update(int i, T x){
    i += N - 1;
    ST[i] = x;
    while (i > 0){
      i = (i - 1) / 2;
      ST[i] = ST[i * 2 + 1] + ST[i * 2 + 2];
    }
  }
  T query(int L, int R, int i, int l, int r){
    if (r <= L || R <= l){
      return E;
    } else if (L <= l && r <= R){
      return ST[i];
    } else {
      int m = (l + r) / 2;
      return query(L, R, i * 2 + 1, l, m) + query(L, R, i * 2 + 2, m, r);
    }
  }
  T query(int L, int R){
    return query(L, R, 0, 0, N);
  }
};
template <typename T>
struct euler_tour{
  vector<int> left, right;
  vector<T> A;
  segment_tree<T> ST;
  lowest_common_ancestor LCA;
  void dfs(vector<vector<int>> &ch, vector<T> &a, int v = 0){
    left[v] = A.size();
    A.push_back(a[v]);
    for (int w : ch[v]){
      dfs(ch, a, w);
    }
    right[v] = A.size();
    A.push_back(-a[v]);
  }
  euler_tour(vector<vector<int>> &ch, vector<T> &a, T E){
    int N = a.size();
    left = vector<int>(N, 0);
    right = vector<int>(N, 0);
    dfs(ch, a);
    LCA = lowest_common_ancestor(ch);
    ST = segment_tree(A, E);
  }
  void update(int v, T x){
    ST.update(left[v], x);
    ST.update(right[v], -x);
  }
  T query(int v, int w){
    int u = LCA.lca(v, w);
    return ST.query(left[u], left[v] + 1) + ST.query(left[u] + 1, left[w] + 1) - ST.query(left[u], left[u] + 1);
  }
  void debug(){
    ST.debug(A.size());
  }
};
pair<int, int> operator +(pair<int, int> A, pair<int, int> B){
  return make_pair(A.first + B.first, A.second + B.second);
}
pair<int, int> operator -(pair<int, int> A, pair<int, int> B){
  return make_pair(A.first - B.first, A.second - B.second);
}
pair<int, int> operator -(pair<int, int> A){
  return make_pair(-A.first, -A.second);
}
int main(){
  int N, Q;
  cin >> N >> Q;
  vector<vector<tuple<int, int, int>>> E(N);
  for (int i = 0; i < N - 1; i++){
    int a, b, c, d;
    cin >> a >> b >> c >> d;
    a--;
    b--;
    E[a].push_back(make_tuple(b, c, d));
    E[b].push_back(make_tuple(a, c, d));
  }
  vector<int> c(N), d(N, 0);
  vector<int> p(N, -1);
  queue<int> q;
  q.push(0);
  while (!q.empty()){
    int v = q.front();
    q.pop();
    for (auto edge : E[v]){
      int w = get<0>(edge);
      if (w != p[v] && w != 0){
        p[w] = v;
        c[w] = get<1>(edge);
        d[w] = get<2>(edge);
        q.push(w);
      }
    }
  }
  map<int, vector<int>> mp;
  for (int i = 1; i < N; i++){
    mp[c[i]].push_back(i);
  }
  vector<vector<int>> ch(N);
  for (int i = 1; i < N; i++){
    ch[p[i]].push_back(i);
  }
  vector<pair<int, int>> d2(N);
  for (int i = 0; i < N; i++){
    d2[i] = make_pair(d[i], 0);
  }
  euler_tour<pair<int, int>> T(ch, d2, make_pair(0, 0));
  vector<tuple<int, int, int, int, int>> query(Q);
  for (int i = 0; i < Q; i++){
    int x, y, u, v;
    cin >> x >> y >> u >> v;
    u--;
    v--;
    query[i] = make_tuple(x, y, u, v, i);
  }
  sort(query.begin(), query.end());
  int color = -1;
  vector<int> ans(Q);
  for (int i = 0; i < Q; i++){
    int x = get<0>(query[i]);
    int y = get<1>(query[i]);
    int u = get<2>(query[i]);
    int v = get<3>(query[i]);
    int id = get<4>(query[i]);
    if (color != x){
      if (color != -1){
        for (int w : mp[color]){
          T.update(w, d2[w]);
        }
      }
      color = x;
      for (int w : mp[color]){
        T.update(w, make_pair(0, 1));
      }
    }
    pair<int, int> tmp = T.query(u, v);
    ans[id] = tmp.first + tmp.second * y;
  }
  for (int i = 0; i < Q; i++){
    cout << ans[i] << endl;
  }
}

Measured memory_bytes: 45808