#include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; i < (n); ++i)
#define sz(x) int(x.size())
#define show(x) {for(auto i: x){cout << i << " ";} cout << endl;}
using namespace std;
using ll = long long;
using P = pair<int, int>;

template<typename T>
struct lca {
    int n, root, l;
    vector<vector<int>> to;
    vector<vector<T>> co;
    vector<int> dep;
    vector<T> costs;
    vector<vector<int>> par;
    lca(int n):n(n), to(n), co(n), dep(n), costs(n) {
        l = 0;
        while ((1<<l) < n) ++l;
        par = vector<vector<int>>(n+1, vector<int>(l, n));
    }
    void addEdge(int a, int b, T c=0) {
        to[a].push_back(b); co[a].push_back(c);
        to[b].push_back(a); co[b].push_back(c);
    }
    void dfs(int v, int d=0, T c=0, int p=-1) {
        if (p != -1) par[v][0] = p;
        dep[v] = d;
        costs[v] = c;
        for (int i = 0; i < to[v].size(); ++i) {
            int u = to[v][i];
            if (u == p) continue;
            dfs(u, d+1, c+co[v][i], v);
        }
    }
    void init(int _root=0) {
        root = _root;
        dfs(root);
        for (int i = 0; i < l-1; ++i) {
            for (int v = 0; v < n; ++v) {
                par[v][i+1] = par[par[v][i]][i];
            }
        }
    }
    // LCA
    int operator()(int a, int b) {
        if (dep[a] > dep[b]) swap(a, b);
        int gap = dep[b] - dep[a];
        for (int i = l-1; i >= 0; --i) {
            int len = 1<<i;
            if (gap >= len) {
                    gap -= len;
                    b = par[b][i];
            }
        }
        if (a == b) return a;
        for (int i = l-1; i >= 0; --i) {
            int na = par[a][i];
            int nb = par[b][i];
            if (na != nb) a = na, b = nb;
        }
        return par[a][0];
    }
    int length(int a, int b) {
        int c = lca(a, b);
        return dep[a] + dep[b] - dep[c]*2;
    }
    T dist(int a, int b) {
        int c = lca(a,b);
        return costs[a]+costs[b]-costs[c]*2;
    }
};
// lca<ll> g(N);  g.addEdge(a, b, cost);  g.init(); //←initialize dep, cost, par
// int common = g(a, b);  int x = g.costs[a];

const int MX = 100005;
struct Edge {
    int to, cost, col;
    Edge(int to, int cost, int col): to(to), cost(cost), col(col) {}
};
vector<Edge> es[MX];

vector<ll> ans;
struct Query {
    int col, qid, coef, y;
    Query(int col, int qid, int coef, int y): col(col), qid(qid), coef(coef), y(y) {}
};
vector<Query> qs[MX];
int cnt[MX];
ll sum[MX];

void dfs2(int v, int p=-1) {
    for (auto q : qs[v]) {
        ll x = -sum[q.col];
        x += (ll)q.y * cnt[q.col];
        ans[q.qid] += x * q.coef;
    }
    for (auto e : es[v]) {
        if (e.to == p) continue;
        cnt[e.col]++; sum[e.col] += e.cost;
        dfs2(e.to, v);
        cnt[e.col]--; sum[e.col] -= e.cost;
    }
}

int main() {
    // クエリ先読み、その色の辺の数とcostの合計を 頂点ごとに保持
    int N, Q;
    cin >> N >> Q;
    lca<ll> graph(N);
    rep(i, N-1) {
        int a, b, c, d;
        cin >> a >> b >> c >> d;
        --a; --b;
        es[a].emplace_back(b, d, c);
        es[b].emplace_back(a, d, c);
        graph.addEdge(a, b, d);
    }
    graph.init();
    ans = vector<ll> (Q);
    rep(i, Q) {
        int x, y, a, b;
        cin >> x >> y >> a >> b;
        --a; --b;
        int c = graph(a, b);
        ans[i] = graph.costs[a] + graph.costs[b] - graph.costs[c] * 2;
        qs[a].emplace_back(x, i, 1, y);
        qs[b].emplace_back(x, i, 1, y);
        qs[c].emplace_back(x, i, -2, y);
    }
    dfs2(0);
    rep(i, Q) printf("%lld\n", ans[i]);
    return 0;
}

Measured memory_bytes: 47776