#include <bits/stdc++.h>
using namespace std;

template<typename T>
struct edge{ int to, color; T cost; };

template<typename T>
struct LCA{
    vector<vector<int>> parent;// parent[v][i] = (2^i)th parent of v
    vector<int> depth;
    vector<T> cost;

    /* constructor (initialize) */
    LCA(const vector<vector<edge<T>>> &graph, int root){
        int n = (int)graph.size();
        depth.assign(n, -1);
        cost.resize(n);

        int h = 1;
        while((1<<h) < n) h += 1;
        parent.assign(n, vector<int>(h, -1));

        DFS(graph, root, -1, 0, 0);// root (depth 0) has no parent (-1)

        // fill entries of parent[v][non-zero]
        for(int i=0; i+1<h; i++){
            for(int v=0; v<n; v++){
                if(parent[v][i] != -1) parent[v][i+1] = parent[parent[v][i]][i];// 2^(i+1) = 2^i * 2
            }
        }
    }

    // fill entries of parent[v][0] and depth[v], cost[v]
    void DFS(const vector<vector<edge<T>>> &graph, int v, int v_parent, int d, T c){
        depth[v] = d;
        cost[v]  = c;
        parent[v][0] = v_parent;// 2^0 = 1

        for(int i=0; i<graph[v].size(); i++){
            if(graph[v][i].to == v_parent) continue;

            int v_child = graph[v][i].to;
            DFS(graph, v_child, v, d+1 , c+graph[v][i].cost);
        }
    }

    int ans(int u, int v){
        if(depth[u] > depth[v]) swap(u,v);// make v deeper

        // align depths
      	int diff = depth[v] - depth[u];
        for(int i=(int)parent[v].size()-1; i>=0; i--){
            if(diff >> i & 1){// go up (update)
                v = parent[v][i];// v -> v'
            }
        }
        // trivial case
        if(u == v) return u;

        // binary search
        for(int i=(int)parent[v].size()-1; i>=0; i--){
            if(parent[u][i] != parent[v][i]){// go up (update)
                u = parent[u][i];// u -> u'
                v = parent[v][i];// v -> v'
            }
        }
        return parent[u][0];
    }
};

template<typename T>
struct query{ int id, color, factor; T new_cost; };

vector<vector<edge<long long int>>> graph;
vector<vector<query<long long int>>> qs;// for each node
vector<int> num;
vector<long long int> total;
vector<long long int> ans;// for each query

void DFS(int v, int parent_v = -1){
    for(auto q : qs[v]){
        ans[q.id] += (q.new_cost * num[q.color] - total[q.color]) * q.factor;
        // u     : +1, 
        // v     : +1, 
        // (u,v) : -2
    }
    for(auto e : graph[v]){
        if(e.to == parent_v) continue;

        num[e.color] += 1;
        total[e.color] += e.cost;

        DFS(e.to, v);

        num[e.color] -= 1;
        total[e.color] -= e.cost;

    }
}

int main(){
    int n, q;
    cin >> n >> q;
    graph.resize(n);
    qs.resize(n);
    num.resize(n);
    total.resize(n);
    ans.resize(q);

    for(int i=0; i<n-1; i++){
        int a, b, c, d;
        cin >> a >> b >> c >> d;
        a -= 1;
        b -= 1;
        graph[a].push_back({b,c,d});
        graph[b].push_back({a,c,d});
    }

    LCA<long long int> lca(graph, 0);
    
    for(int i=0; i<q; i++){
        int x, y, u, v;
        cin >> x >> y >> u >> v;
        u -= 1;
        v -= 1;

        int w = lca.ans(u,v);
        ans[i] = lca.cost[u] + lca.cost[v] - 2 * lca.cost[w];
        qs[u].push_back({i,x,+1,y});
        qs[v].push_back({i,x,+1,y});
        qs[w].push_back({i,x,-2,y});
    }

    DFS(0);
    for(int i=0; i<q; i++){
        cout << ans[i] << endl;
    }
    return 0;
}


Measured memory_bytes: 41312