#include <cassert>
#include <iostream>
#include <map>
#include <tuple>
#include <vector>

using Edge = std::tuple<int, int, int>;
using Graph = std::vector<std::vector<Edge>>;

/// LCA (Lowest Common Ancestor) by doubling.
///
/// The calculation order is as follows:
///
/// - Construction: O(N logN)
/// - Query: O(logN)
///
/// Usage example:
///
/// ```
/// int root = 0;
/// LowestCommonAncestor lca(G, root);
///
/// for (int q = 0; q < Q; ++q) {
///   int u, v;
///   std::cin >> u >> v;
///   std::cout << lca(u, v) << std::endl;
/// }
/// ```
class LowestCommonAncestor {
public:
  LowestCommonAncestor(const Graph &G, const int root) {
    // Get size
    N = G.size();
    M = 1; // 2^{M - 1} < N <= 2^M or M = ceil(log(N - 1)) + 1
    while ((1 << M) < N)
      ++M;

    // Reserve memory
    parent.assign(N, std::vector<int>(M, -1));
    depth.assign(N, -1);

    // Set depth and immediate parent
    dfs(G, root, -1, 0);

    // Seek ancestors by doubling
    for (int k = 1; k < M; ++k)
      for (int i = 0; i < N; ++i)
        if (parent[i][k - 1] != -1)
          parent[i][k] = parent[parent[i][k - 1]][k - 1];
  }

  int operator()(int u, int v) const {
    if (depth[u] > depth[v])
      std::swap(u, v);

    // Lift `v` by `depth[v] - depth[u]` generations to align the depth
    for (int k = 0; k < M; ++k)
      if ((depth[v] - depth[u]) & (1 << k))
        v = parent[v][k];

    // Find lowest common ancestor
    if (u == v)
      return u;
    for (int k = M - 1; k >= 0; --k) {
      if (parent[u][k] != parent[v][k]) {
        u = parent[u][k];
        v = parent[v][k];
      }
    }
    return parent[u][0];
  }

private:
  int N;                                // number of nodes
  int M;                                // number of doublings
  std::vector<std::vector<int>> parent; // parent[v][d] := 2^d-th parent of v
  std::vector<int> depth;

  // Set depth and immediate parent
  void dfs(const Graph &G, const int v, const int p, const int d) {
    parent[v][0] = p;
    depth[v] = d;
    for (auto e : G[v]) {
      if (std::get<0>(e) == p)
        continue;
      dfs(G, std::get<0>(e), v, d + 1);
    }
  }
};

void dfs(const Graph &G, const int v, const int p,
         const std::vector<std::vector<int>> &necessary,
         std::map<int, int> &currentNum, std::map<int, int> &currentSum,
         std::vector<std::map<int, int>> &num,
         std::vector<std::map<int, int>> &sum, std::vector<int> &dist) {

  // Calculation on the current node v
  for (auto color : necessary[v]) {
    num[v][color] = currentNum[color];
    sum[v][color] = currentSum[color];
  }

  for (auto e : G[v]) {
    if (std::get<0>(e) == p)
      continue;

    int c = std::get<1>(e);
    int d = std::get<2>(e);
    currentNum[c] += 1;
    currentSum[c] += d;

    assert(dist[v] >= 0);
    dist[std::get<0>(e)] = dist[v] + d;
    dfs(G, std::get<0>(e), v, necessary, currentNum, currentSum, num, sum,
        dist);

    currentNum[c] -= 1;
    currentSum[c] -= d;
  }
}

int main() {
  int N, Q;
  std::cin >> N >> Q;
  std::vector<int> a(N - 1), b(N - 1), c(N - 1), d(N - 1);
  for (int i = 0; i < N - 1; ++i) {
    std::cin >> a[i] >> b[i] >> c[i] >> d[i];
    --a[i], --b[i], --c[i];
  }
  std::vector<int> x(Q), y(Q), u(Q), v(Q);
  for (int q = 0; q < Q; ++q) {
    std::cin >> x[q] >> y[q] >> u[q] >> v[q];
    --x[q], --u[q], --v[q];
  }

  Graph G(N);
  for (int i = 0; i < N - 1; ++i) {
    G[a[i]].push_back(std::make_tuple(b[i], c[i], d[i]));
    G[b[i]].push_back(std::make_tuple(a[i], c[i], d[i]));
  }

  int root = 0;
  LowestCommonAncestor lca(G, root);

  // Necessary colors for each node in the future
  std::vector<std::vector<int>> necessary(N);
  for (int q = 0; q < Q; ++q) {
    necessary[u[q]].push_back(x[q]);
    necessary[v[q]].push_back(x[q]);
    necessary[lca(u[q], v[q])].push_back(x[q]); // NOTE: I forgot this!
  }

  std::vector<int> dist(N, -1);
  dist[root] = 0;

  // map with information from current node to root
  std::map<int, int> currentNum;
  std::map<int, int> currentSum;
  for (int c = 0; c < N; ++c) {
    currentNum[c] = 0;
    currentSum[c] = 0;
  }

  std::vector<std::map<int, int>> num(N);
  std::vector<std::map<int, int>> sum(N);

  dfs(G, root, -1, necessary, currentNum, currentSum, num, sum, dist);

  // Query
  for (int q = 0; q < Q; ++q) {
    int u_ = u[q];
    int v_ = v[q];
    int uv_ = lca(u_, v_);

    int d_u = dist[u_];
    int d_v = dist[v_];
    int d_uv = dist[uv_];

    int c = x[q];
    d_u += num[u_][c] * y[q] - sum[u_][c];
    d_v += num[v_][c] * y[q] - sum[v_][c];
    d_uv += num[uv_][c] * y[q] - sum[uv_][c];
    std::cout << d_u + d_v - 2 * d_uv << std::endl;
  }

  return 0;
}


Measured memory_bytes: 75576