#include <iostream>
#include <algorithm>
#include <functional>
#include <vector>
#include <set>
#include <map>
#include <stack>
#include <queue>
#include <string>
#include <numeric>
#include <cmath>
#include <bitset>

#define rep(i, n) for (int i = 0; i < n; i++)
using namespace std;
typedef long long ll;
using P = pair<ll, ll>;

template<class T> inline bool chmin(T& a,T b) {if (a > b) {a = b; return true;} return false;}
template<class T> inline bool chmax(T& a,T b) {if (a < b) {a = b; return true;} return false;}

const ll MOD = 1000000007;
const int INF = 1<<30;
//const ll INF = (ll)1e18 + 1;

struct edge{
  int to, co, col;
  edge(int to, int co, int col): to(to), co(co), col(col){}
};
using Graph = vector<vector<edge>>;
struct LCA{
  vector<vector<int>> par; //par[k][u]:= u の 2^k 先の親
  vector<int> dist;        //rootからの距離
  LCA(const Graph& G, int root = 0) {init (G, root);}

  void init(const Graph& G, int root = 0){
    int V = G.size();
    int K = 1;
    while ((1 << K) < V) K++;
    par.assign(K, vector<int>(V, -1));
    dist.assign(V, -1);
    dfs(G, root, -1, 0);
    for (int k = 0; k + 1 < K; ++k){
      for (int v = 0; v < V; ++v){
        if (par[k][v] < 0) par[k + 1][v] = -1;
        else par[k + 1][v] = par[k][par[k][v]];
      }
    }
  }

  //根からの距離と1つ先の頂点を求める
  void dfs(const Graph& G, int v, int p, int d){
    par[0][v] = p;
    dist[v] = d;
    for (auto e: G[v]){
      if (e.to != p) dfs(G, e.to, v, d + 1);
    }
  }

  int query(int u, int v){
    if (dist[u] < dist[v]) swap(u, v); //uを必ず深くする
    int K = par.size();
    //LCAまでの距離を同じにする
    for (int k = 0; k < K; ++k){
      if ((dist[u] - dist[v] >> k) & 1) u = par[k][u];
    }
    //二分探索でLCAを求める
    if (u == v) return u;
    for (int k = K - 1; k >= 0; k--){
      if (par[k][u] != par[k][v]){
        u = par[k][u];
        v = par[k][v];
      }
    }
    return par[0][u];
  }
  int get_dist(int u, int v){
    return dist[u] + dist[v] - 2 * dist[query(u, v)];
  }
  //aがuとvを結ぶパス上にあるかどうか
  bool is_on_path(int u, int v, int a){
    return get_dist(u, a) + get_dist(a, v) == get_dist(u, v);
  }
};
Graph G(101010);
int N, Q;
int dist[101010];
vector<int> need[101010];
map<int, int> res_num[101010], res_sum[101010];

int now_num[101010], now_sum[101010];
void dfs(int v, int p = -1){
  for (int c: need[v]){
    res_num[v][c] = now_num[c];
    res_sum[v][c] = now_sum[c];
  }
  for (auto e: G[v]){
    int to = e.to, c = e.col, d = e.co;
    if (to == p) continue;
    dist[to] = dist[v] + d;
    now_num[c]++;
    now_sum[c] += d;
    dfs(to, v);
    now_num[c]--;
    now_sum[c] -= d;
  }
}

int main(){
  cin >> N >> Q;
  rep(i, N - 1){
    int a, b, c, d; cin >> a >> b >> c >> d;
    a--, b--, c--;
    G[a].emplace_back(b, d, c);
    G[b].emplace_back(a, d, c);
  }
  LCA lca(G, 0);

  vector<int> X(Q), Y(Q), U(Q), V(Q), L(Q);
  rep(i, Q){
    cin >> X[i] >> Y[i] >> U[i] >> V[i];
    X[i]--, U[i]--, V[i]--;

    L[i] = lca.query(U[i], V[i]);
    need[U[i]].push_back(X[i]);
    need[V[i]].push_back(X[i]);
    need[L[i]].push_back(X[i]);
  }
  dfs(0, -1);
  rep(i, Q){
    int x = X[i], y = Y[i], u = U[i], v = V[i], l = L[i];
    int du = dist[u] - res_sum[u][x] + res_num[u][x] * y;
    int dv = dist[v] - res_sum[v][x] + res_num[v][x] * y;
    int dl = dist[l] - res_sum[l][x] + res_num[l][x] * y;
    int ans = du + dv - 2 * dl;
    cout << ans << endl;
  }
}


Measured memory_bytes: 59436