#include <bits/stdc++.h>
using namespace std;
using Int = long long;
struct Edge {
    int src, dst, color, weight;
    Edge(int s, int d, int c, int w) : src(s), dst(d), color(c), weight(w) {}
};
using Graph = vector<vector<Edge>>;
struct LCA {
    vector<vector<int>> parent;
    vector<int> depth;
    LCA(const Graph &g, int root) {
        parent.resize(g.size(), vector<int>(32 - __builtin_clz(g.size())));
        depth.resize(g.size());
        function<void(int, int)> recur = [&](int node, int prev) {
            if (prev == -1) {
                depth[node] = 0;
                parent[node][0] = node;
            } else {
                depth[node] = depth[prev] + 1;
                parent[node][0] = prev;
            }
            for (auto &e : g[node]) {
                if (e.dst == prev) continue;
                recur(e.dst, node);
            }
        };
        recur(root, -1);
        for (int i = 1; i < parent[0].size(); i++) {
            for (int j = 0; j < parent.size(); j++) {
                parent[j][i] = parent[parent[j][i-1]][i-1];
            }
        }
    }
    int query(int x, int y) {
        if (depth[x] != depth[y]) {
            if (depth[x] < depth[y]) swap(x, y);
            for (int i = parent[x].size()-1; i >= 0; i--) {
                if (depth[parent[x][i]] >= depth[y]) {
                    x = parent[x][i];
                }
            }
        }
        assert(depth[x] == depth[y]);
        if (x == y) return x;
        for (int i = parent[x].size()-1; i >= 0; i--) {
            if (parent[x][i] != parent[y][i]) {
                x = parent[x][i];
                y = parent[y][i];
            }
        }
        return parent[x][0];
    }
};
int main() {
    int N, Q; cin >> N >> Q;
    Graph G(N);
    for (int i = 0; i < N-1; i++) {
        int a, b, c, d; cin >> a >> b >> c >> d; a--, b--;
        G[a].emplace_back(a, b, c, d);
        G[b].emplace_back(b, a, c, d);
    }
    LCA lca(G, 0);
    vector<int> X(Q), Y(Q), U(Q), V(Q);
    vector<map<int, pair<int, int>>> memo(N);
    for (int i = 0; i < Q; i++) {
        cin >> X[i] >> Y[i] >> U[i] >> V[i];
        U[i]--, V[i]--;
        int a = lca.query(U[i], V[i]);
        memo[U[i]][0] = memo[V[i]][0] = memo[a][0] = make_pair(0, 0);
        memo[U[i]][X[i]] = memo[V[i]][X[i]] = memo[a][X[i]] = make_pair(0, 0);
    }
    vector<pair<int, int>> color(N);
    function<void(int, int)> recur = [&](int node, int prev) {
        for (auto &p : memo[node]) {
            p.second = color[p.first];
        }
        for (auto &e : G[node]) {
            if (e.dst == prev) continue;
            color[0].first += e.weight;
            color[0].second += 1;
            color[e.color].first += e.weight;
            color[e.color].second += 1;
            recur(e.dst, node);
            color[0].first -= e.weight;
            color[0].second -= 1;
            color[e.color].first -= e.weight;
            color[e.color].second -= 1;
        }
    };
    recur(0, -1);
    for (int i = 0; i < Q; i++) {
        int a = lca.query(U[i], V[i]);
        int d = memo[U[i]][0].first + memo[V[i]][0].first - 2*memo[a][0].first;
        int cn = memo[U[i]][X[i]].second + memo[V[i]][X[i]].second - 2*memo[a][X[i]].second;
        int cd = memo[U[i]][X[i]].first + memo[V[i]][X[i]].first - 2*memo[a][X[i]].first;
        cout << d - cd + cn * Y[i] << '\n';
    }
    return 0;
}

Measured memory_bytes: 49016