#include <bits/stdc++.h>
#define debug(x) cerr << #x << ": " << x << '\n';
using namespace std;
using ll = long long;
using P = pair<int, int>;
const int INF = (int)1e9;
const int MOD = (int)1e9 + 7;

// graph template
template<typename T>
class Edge{
    public:
        int src, to; T cost;
        int color;

        Edge(int to, T cost): src(-1), to(to), cost(cost){}
        Edge(int src, int to, T cost, int color): src(src), to(to), cost(cost), color(color){}
};
template<typename T>
using Edges = vector<Edge<T>>;
template<typename T>
using AdjacencyList = vector<Edges<T>>;
template<typename T>
using Matrix = vector<vector<T>>;

template<typename T>
class LowestCommonAncestor{
    private:
        AdjacencyList<T> g;
        vector<vector<int>> par; // parent[v][i]: 2^i回親を辿って到達する頂点
        vector<int> depth;
        vector<T> costs;
        int V, root, l;

         void dfs(int v, int d = 0 , T c = 0, int p = -1){
            if(p != -1) par[v][0] = p;
            depth[v] = d;
            costs[v] = c;
            for(auto e: g[v]){
                if(e.to == p) continue;
                dfs(e.to, d+1, c+e.cost, v);
            }
        }

    public:
        LowestCommonAncestor(const AdjacencyList<T> &g): g(g), depth(g.size()), costs(g.size()), V(g.size()), l(0){
            while(1 << l++ < V);
            par = vector<vector<int>>(V+1, vector<int>(l, V));
        }

        void init(int root = 0){
            this -> root = root;
            dfs(root);
            for(int i = 0; i < l - 1; i++){
                for(int v = 0; v < V; v++){
                    if(par[v][i] != -1){
                        par[v][i+1] = par[par[v][i]][i];
                    }
                }
            }
        }

        int lca(int a, int b){
            if(depth[a] > depth[b]) swap(a, b);
            int gap = depth[b] - depth[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 nb = par[a][i];
                int na = par[b][i];
                if(nb != na) a = na, b = nb;
            }
            return par[a][0];
        }

        int length(int a, int b){
            int c = this -> lca(a, b);
            return depth[a] + depth[b] - 2*depth[c];
        }

        int dist(int a, int b){
            int c = this -> lca(a, b);
            return costs[a] + costs[b] - 2*costs[c];
        }
};

struct Query{
    int qid, color, y, coeff;
    Query(int qid, int color, int y, int coeff): qid(qid), color(color), y(y), coeff(coeff){}
};

vector<vector<Query>> qs(100005);
int cnt[100005];
ll sum[100005];

void dfs(int v, AdjacencyList<int> &g, vector<ll> &res, int p = -1){
    for(auto q: qs[v]){
        ll x = -sum[q.color];
        x += (ll)cnt[q.color]*q.y;
        res[q.qid] += x*q.coeff;
    }
    for(auto e: g[v]){
        if(e.to == p) continue;
        cnt[e.color]++;
        sum[e.color] += e.cost;
        dfs(e.to, g, res, v);
        cnt[e.color]--;
        sum[e.color] -= e.cost;
    }
}

int main(void){
    int N, Q;
    cin >> N >> Q;
    AdjacencyList<int> 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(Edge<int>(a, b, d, c));
        g[b].emplace_back(Edge<int>(b, a, d, c));
    }

    vector<ll> res(Q);
    LowestCommonAncestor<int> lca(g);
    lca.init();
    for(int i = 0; i < Q; i++){
        int x, y, u, v;
        cin >> x >> y >> u >> v;
        u--; v--;
        int c = lca.lca(u, v);
        res[i] = lca.dist(u, v);
        qs[u].emplace_back(Query(i, x, y, 1));
        qs[v].emplace_back(Query(i, x, y, 1));
        qs[c].emplace_back(Query(i, x, y, -2));
    }
    debug(2);
    dfs(0, g, res);

    for(int i = 0; i < Q; i++){
        cout << res[i] << '\n';
    }

    return 0;
}

Measured memory_bytes: 43252