#include <bits/stdc++.h>

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

class LCA {
  vector<vector<int>> parent;
  vector<int> depth;
  int logV;

  void dfs(int u, int p, int d, vector<vector<int>> &adjacencyList) {
    parent[0][u] = p;
    depth[u] = d;
    for (auto v: adjacencyList[u]) {
      if (v != p) dfs(v, u, d + 1, adjacencyList);
    }
  }

public:

  LCA(vector<vector<int>> &adjacencyList) {
    int V = adjacencyList.size();
    logV = 0;
    while((1<<logV) < V) logV++;
    parent.resize(logV, vector<int>(V));
    depth.resize(V);

    dfs(0, -1, 0, adjacencyList);
    for (int k = 0; k + 1 < logV; k++) {
      for (int v = 0; v < V; v++) {
        if (parent[k][v] < 0) {
          parent[k + 1][v] = -1;
        } else {
          parent[k + 1][v] = parent[k][parent[k][v]];
        }
      }
    }
  } 

  int find(int u, int v) {
    if (depth[u] > depth[v]) swap(u, v);
    for (int k = 0; k < logV; k++) {
      if ((depth[v] - depth[u]) >> k & 1) {
        v = parent[k][v];
      }
    }
    if (u == v) return u;
    for (int k = logV - 1; k >= 0; k--) {
      if (parent[k][u] != parent[k][v]) {
        u = parent[k][u];
        v = parent[k][v];
      }
    }
    return parent[0][u];
  }
};

struct query {
  int x, y, u, v, lca;
};

class ColorfulTree {
  struct edge {
    int dest, color, distance;
  };

  vector<vector<edge>> G;
  vector<vector<int>> adj;
  vector<set<int>> relevantColor;

  vector<int> monochroDistance;
  map<int, map<int, int>> colorDistance;
  map<int, map<int, int>> colorNum;

  int V;
  int E;

  void dfs(int u, int parent, vector<int> &tmpColorDist, vector<int> &tmpColorNum) {
    for (int c: relevantColor[u]) {
      colorDistance[c][u] = tmpColorDist[c];
      colorNum[c][u] = tmpColorNum[c];
    }

    for (auto &e: G[u]) {
      if (e.dest != parent) {
        tmpColorDist[e.color] += e.distance;
        tmpColorNum[e.color]++;
        monochroDistance[e.dest] = monochroDistance[u] + e.distance;

        dfs(e.dest, u, tmpColorDist, tmpColorNum);
        tmpColorDist[e.color] -= e.distance;
        tmpColorNum[e.color]--;
      }
    }
  }

  int distanceBetweenNodes(auto &d, query &q) {
    return d[q.u] + d[q.v] - 2 * d[q.lca];
  };

public:

  ColorfulTree(int _V) {
    V = _V;
    E = V - 1;
    G.resize(V);
    adj.resize(V);
    relevantColor.resize(V);
  }

  void addEdge(int u, int v, int color, int distance) {
    G[u].push_back(edge{v, color, distance});
    G[v].push_back(edge{u, color, distance});
    adj[u].push_back(v);
    adj[v].push_back(u);
  }

  vector<vector<int>>& adjacencyList() {
    return adj;
  }

  void relevant(int color, int u) {
    relevantColor[u].insert(color);
  }

  void collectDistances() {
    monochroDistance.resize(V);
    vector<int> tmpColorDist(E, 0);
    vector<int> tmpColorNum(E, 0);
    dfs(0, -1, tmpColorDist, tmpColorNum);
  }

  int process(query &q) {
    int d = distanceBetweenNodes(monochroDistance, q);
    int cd = distanceBetweenNodes(colorDistance[q.x], q);
    int n = distanceBetweenNodes(colorNum[q.x], q);
    return d - cd + n * q.y;
  }
};

int main() {
  int N, Q;
  cin >> N >> Q;

  ColorfulTree t(N);

  rep(i, N - 1) {
    int a, b, c, d;
    cin >> a >> b >> c >> d;
    a--;
    b--;
    c--;
    t.addEdge(a, b, c, d);
  }

  auto G = t.adjacencyList();
  LCA lca(G);

  vector <query> queries(Q);
  rep(i, Q) {
    int x, y, u, v;
    cin >> x >> y >> u >> v;
    x--;
    u--;
    v--;
    int l = lca.find(u, v);
    queries[i] = query{x, y, u, v, l};
    t.relevant(x, u);
    t.relevant(x, v);
    t.relevant(x, l);
  }

  t.collectDistances();

  for (auto &q: queries) {
    cout << t.process(q) << endl;
  }

  return 0;
}


Measured memory_bytes: 76464