#include"bits/stdc++.h"
using namespace std;
using ll = int64_t;

struct Edge {
    Edge(ll t, ll c, ll d) : to(t), color(c), distance(d) {}
    ll to, color, distance;
};

struct Query {
    ll x, y, u, v;
};

class LCA {
public:
    LCA(const vector<vector<Edge>>& edges, ll root) : n_(edges.size()), log2_n_(log2(n_) + 1),
            parent_(log2_n_, vector<ll>(n_)), depth_(n_) {
        dfs(edges, root, -1, 0);
        for (ll k = 0; k + 1 < log2_n_; k++) {
            for (ll v = 0; v < n_; v++) {
                parent_[k + 1][v] = (parent_[k][v] < 0 ? -1 : parent_[k][parent_[k][v]]);
            }
        }
    }

    ll get(ll u, ll v) {
        if (depth_[u] > depth_[v]) {
            swap(u, v);
        }
        for (ll k = 0; k < log2_n_; k++) {
            if ((depth_[v] - depth_[u]) >> k & 1) {
                v = parent_[k][v];
            }
        }
        if (u == v) {
            return u;
        }
        for (ll k = log2_n_ - 1; k >= 0; k--) {
            if (parent_[k][u] != parent_[k][v]) {
                u = parent_[k][u];
                v = parent_[k][v];
            }
        }
        return parent_[0][u];
    }
private:
    void dfs(const vector<vector<Edge>>& edges, ll curr, ll pre, ll depth) {
        parent_[0][curr] = pre;
        depth_[curr] = depth;
        for (Edge e : edges[curr]) {
            if (e.to == pre) {
                continue;
            }
            dfs(edges, e.to, curr, depth + 1);
        }
    }

    const ll n_;
    const ll log2_n_;
    vector<vector<ll>> parent_;
    vector<ll> depth_;
};

int main() {
    ll N, Q;
    cin >> N >> Q;
    vector<vector<Edge>> edges(N);
    for (ll i = 0; i < N - 1; i++) {
        ll a, b, c, d;
        cin >> a >> b >> c >> d;
        a--; b--; c--;
        edges[a].emplace_back(b, c, d);
        edges[b].emplace_back(a, c, d);
    }

    vector<Query> queries(Q);
    for (Query& q : queries) {
        cin >> q.x >> q.y >> q.u >> q.v;
        q.x--; q.u--; q.v--;
    }

    //queries[i]に答えるために必要なのは、rootからu, v, LCA(u, v)への
    //(1)通常時の距離
    //(2)経路上におけるx色をした辺の本数

    //まず距離を求めてしまう
    vector<ll> distance_from_root(N, LLONG_MAX);
    stack<ll> st;
    st.push(0);
    distance_from_root[0] = 0;
    while (!st.empty()) {
        ll curr = st.top();
        st.pop();
        for (const Edge& e : edges[curr]) {
            ll new_dist = distance_from_root[curr] + e.distance;
            if (new_dist < distance_from_root[e.to]) {
                distance_from_root[e.to] = new_dist;
                st.push(e.to);
            }
        }
    }

    //各ノードで何色の情報が必要なのかを記録
    //ここでLCAが必要
    LCA lca(edges, 0);
    vector<vector<ll>> need_color(N);
    for (const Query& q : queries) {
        need_color[q.u].push_back(q.x);
        need_color[q.v].push_back(q.x);
        need_color[lca.get(q.u, q.v)].push_back(q.x);
    }

    //各色の辺の本数を保持しながらDFSして必要なら書き込み
    vector<ll> color_num(N, 0);
    vector<ll> color_dist(N, 0);
    vector<map<ll, ll>> color_num_mp(N);
    vector<map<ll, ll>> color_dist_mp(N);
    function<void(ll, ll)> dfs = [&](ll curr, ll pre) {
        //必要な情報の記録
        for (ll c : need_color[curr]) {
            color_num_mp[curr][c] = color_num[c];
            color_dist_mp[curr][c] = color_dist[c];
        }

        for (const Edge& e : edges[curr]) {
            if (e.to == pre) {
                continue;
            }
            color_num[e.color]++;
            color_dist[e.color] += e.distance;
            dfs(e.to, curr);
            color_num[e.color]--;
            color_dist[e.color] -= e.distance;
        }
    };
    dfs(0, -1);

    //各queryに答える
    for (const Query q : queries) {
        ll l = lca.get(q.v, q.u);
        ll dist = distance_from_root[q.u] + distance_from_root[q.v] - 2 * distance_from_root[l];
        ll c_dist = color_dist_mp[q.u][q.x] + color_dist_mp[q.v][q.x] - 2 * color_dist_mp[l][q.x];
        ll change_num = color_num_mp[q.u][q.x] + color_num_mp[q.v][q.x] - 2 * color_num_mp[l][q.x];
        ll ans = dist - c_dist + change_num * q.y;
        cout << ans << endl;
    }
}

Measured memory_bytes: 78116