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

struct HLDecomposition{
    vector<vector<int>> G;
    int N;
    vector<int> sz, in, out, head, rev, par;

    HLDecomposition(vector<vector<int>> G):
    G(G), N(G.size()), sz(G.size()), in(G.size()), out(G.size()), head(G.size()), rev(G.size()), par(G.size()) {
        build();
    }

    void dfs_sz(int i, int p){
        par[i] = p;
        sz[i] = 1;
        if(G[i].size() && G[i][0] == p) swap(G[i][0], G[i].back());
        for(auto& j : G[i]){
            if(j == p) continue;
            dfs_sz(j, i);
            sz[i] += sz[j];
            if(sz[G[i][0]] < sz[j]) swap(G[i][0], j);
        }
    }

    void dfs_hld(int i, int p, int& times){
        in[i] = times++;
        rev[in[i]] = i;
        for(auto& j : G[i]){
            if(j == p) continue;
            head[j] = (G[i][0]==j ? head[i] : j);
            dfs_hld(j, i, times);
        }
    }

    void build(){
        dfs_sz(0, -1);
        int t = 0;
        dfs_hld(0, -1, t);
    }

    int la(int v, int k){
        while(true){
            int u = head[v];
            if(in[v]-k >= in[u]) return rev[in[v]-k];
            k -= in[v]-in[u]+1;
            v = par[u];
        }
    }

    int lca(int u, int v){
        for( ; ; v=par[head[v]]){
            if(in[u] > in[v]) swap(u, v);
            if(head[u] == head[v]) return u;
        }
    }

    template<typename T>
    T query(int u, int v, T e, function<T(int, int)> get_between, function<T(T, T)> merge, bool edge=false){
        T l = e, r = e;
        for( ; ; v=par[head[v]]){
            if(in[u] > in[v]) swap(u, v), swap(l, r);
            if(head[u] == head[v]) break;
            l = merge(l, get_between(in[head[v]], in[v]));
        }
        return merge(l, merge(r, get_between(in[u]+edge, in[v])));
    }
};

template<typename T>
struct Segtree {
    int n;
    T e;
    vector<T> dat;
    typedef function<T(T a, T b)> Func;
    Func f;

    Segtree(){}
    Segtree(int n_input, Func f_input, T e_input){
        initialize(n_input, f_input, e_input);
    }
    void initialize(int n_input, Func f_input, T e_input){
        f = f_input;
        e = e_input;
        n = 1;
        while(n < n_input) n <<= 1;
        dat.resize(2*n-1, e);
    }

    void update(int k, T a){
        k += n - 1;
        dat[k] = a;
        while(k > 0){
            k = (k - 1)/2;
            dat[k] = f(dat[2*k+1], dat[2*k+2]);
        }
    }

    T get(int k){
        return dat[k+n-1];
    }

    T between(int a, int b){
        return query(a, b+1, 0, 0, n);
    }

    T query(int a, int b, int k, int l, int r){
        if(r<=a || b<=l) return e;
        if(a<=l && r<=b) return dat[k];
        T vl = query(a, b, 2*k+1, l, (l+r)/2);
        T vr = query(a, b, 2*k+2, (l+r)/2, r);
        return f(vl, vr);
    }
};

int main(){
    int N, Q;
    cin >> N >> Q;
    vector<int> A(N-1), B(N-1), C(N-1), D(N-1);
    vector<vector<int>> edges(N);
    vector<vector<int>> c2e(N-1);
    for(int i=0; i<N-1; i++){
        cin >> A[i] >> B[i] >> C[i] >> D[i];
        A[i]--; B[i]--; C[i]--;
        c2e[C[i]].push_back(i);
        edges[A[i]].push_back(B[i]);
        edges[B[i]].push_back(A[i]);
    }

    HLDecomposition hld(edges);
    typedef pair<int, int> P;
    P Zero = P(0, 0);
    auto sumP = [](P a, P b){ return P(a.first + b.first, a.second + b.second); };
    Segtree<P> st(N, sumP, Zero);
    for(int i=0; i<N-1; i++){
        if(hld.in[A[i]] > hld.in[B[i]]) swap(A[i], B[i]);
        st.update(hld.in[B[i]], P(D[i], 0));
    }

    vector<int> X(Q), Y(Q), U(Q), V(Q);
    vector<vector<int>> c2q(N-1);
    for(int i=0; i<Q; i++){
        cin >> X[i] >> Y[i] >> U[i] >> V[i];
        X[i]--; U[i]--; V[i]--;
        c2q[X[i]].push_back(i);
    }

    vector<int> ans(Q);
    for(int c=0; c<N-1; c++){
        for(int i : c2e[c]) st.update(hld.in[B[i]], P(0, 1));
        for(int i : c2q[c]){
            auto res = hld.query<P>(U[i], V[i], Zero, [&](int i, int j){ return st.between(i, j); }, sumP, true);
            ans[i] = res.first + res.second * Y[i];
        }
        for(int i : c2e[c]) st.update(hld.in[B[i]], P(D[i], 0));
    }

    for(int a : ans) cout << a << endl;
}

Measured memory_bytes: 30292