#include <iostream>
#include <string>
#include <algorithm>
#include <vector>
#include <cmath>
#include <queue>
#include <map>
#include <unordered_map>
#include <set>
#include <functional>
#include <bitset>
#include <numeric>
#include <complex>
#include <iomanip>
#include <cassert>
#include <random>


struct LowestCommonAncestor {
    static const int L = 30;
    using Edge = std::vector<std::vector<int>>;
    std::vector<int> depth;
    std::vector<std::vector<int>> anc;

    LowestCommonAncestor(const Edge &edg, int root)
        : depth(edg.size()), anc(L, std::vector<int>(edg.size(), root)) {

        build(edg, root);
    }

    int query(int u, int v) {
        if (depth[u] > depth[v]) std::swap(u, v);
        for (int i = L - 1; i >= 0; i--) {
            if (((depth[v] - depth[u]) >> i) & 1) {
                v = anc[i][v];
            }
        }
        if (u == v) return u;

        for (int i = L - 1; i >= 0; i--) {
            if (anc[i][u] == anc[i][v]) continue;
            u = anc[i][u];
            v = anc[i][v];
        }
        return anc[0][u];
    }

private:
    void dfs(const Edge &edg, int pos, int prev = -1) {
        for (int v : edg[pos]) {
            if (v == prev) continue;
            depth[v] = depth[pos] + 1;
            anc[0][v] = pos;
            dfs(edg, v, pos);
        }
    }

    void build(const Edge &edg, int root) {
        dfs(edg, root);
        int n = edg.size();
        for (int i = 1; i < L; i++) {
            for (int j = 0; j < n; j++) {
                anc[i][j] = anc[i - 1][anc[i - 1][j]];
            }
        }
    }
};


int main() {
    int n, q; std::cin >> n >> q;
    std::vector<std::vector<int>> edg(n), col(n), dist(n);
    for (int i = 0; i < n - 1; i++) {
        int a, b, c, d; std::cin >> a >> b >> c >> d;
        a--; b--; c--;
        edg[a].push_back(b);
        edg[b].push_back(a);
        col[a].push_back(c);
        col[b].push_back(c);
        dist[a].push_back(d);
        dist[b].push_back(d);
    }
    LowestCommonAncestor lca(edg, 0);
    std::vector<int> x(q), y(q), u(q), v(q);
    std::vector<std::set<int>> ev(n);
    for (int i = 0; i < q; i++) {
        std::cin >> x[i] >> y[i] >> u[i] >> v[i];
        x[i]--; u[i]--; v[i]--;
        ev[u[i]].insert(x[i]);
        ev[v[i]].insert(x[i]);
        ev[lca.query(u[i], v[i])].insert(x[i]);
    }
    std::map<std::pair<int, int>, std::pair<int, int>> mem;
    std::vector<int> cnt(n), sumc(n), sumall(n);
    auto dfs = [&](const auto &self, int pos = 0,
            int prev = -1, int prevd = 0) -> void {
        sumall[pos] = prevd;
        for (int ec : ev[pos]) {
            mem[{pos, ec}] = { cnt[ec], sumc[ec] };
        }
        for (int i = 0; i < (int)edg[pos].size(); i++) {
            int nxt = edg[pos][i];
            if (nxt == prev) continue;
            int c = col[pos][i];
            int d = dist[pos][i];
            cnt[c]++;
            sumc[c] += d;
            self(self, nxt, pos, prevd + d);
            cnt[c]--;
            sumc[c] -= d;
        }
    };
    dfs(dfs);
    for (int i = 0; i < q; i++) {
        int anc = lca.query(u[i], v[i]);
        const auto &up = mem[{u[i], x[i]}];
        const auto &vp = mem[{v[i], x[i]}];
        const auto &ap = mem[{anc, x[i]}];
        int s = up.first + vp.first - 2 * ap.first;
        int d = up.second + vp.second - 2 * ap.second;
        int dall = sumall[u[i]] + sumall[v[i]] - 2 * sumall[anc];
        std::cout << dall - d + s*y[i] << std::endl;
    }
    return 0;
}


Measured memory_bytes: 65516