#include <iostream>
#include <vector>
#include <map>
#include <set>
#include <algorithm>

using namespace std;

using ll =  long long;

constexpr ll V_MAX = 100010;

vector<tuple<int, int, ll>> graph[V_MAX];
vector<ll> dists(V_MAX);
map<ll, int> colormp;
map<ll, ll> distmp;
set<int> required_colors[V_MAX];

class LowestCommonAncestor {
    public:
    int root, n, LOG_V_MAX = 20;
    vector<int> depth;
    vector<vector<int>> parent;

    LowestCommonAncestor(int root=0, int n=V_MAX): root(root), n(n) {
        depth.assign(n, -1);
        parent.assign(n, vector<int>(LOG_V_MAX, -1));
        dfs(root, -1, 0);
        for(int j=1;j<LOG_V_MAX;++j) {
            for(int i=0;i<n;++i) {
                if(parent[i][j-1] == -1) continue;
                parent[i][j] = parent[parent[i][j-1]][j-1];
            }
        }
    }

    void dfs(int node, int par, int d) {
        depth[node] = d;
        parent[node][0] = par;
        for(auto child: graph[node]) {
            int c = get<0>(child);
            if(c == par) continue;
            dfs(c, node, d+1);
        }
    }

    int get_lca(int u, int v) {
        if(depth[u] > depth[v]) swap(u, v);
        int depth_diff = depth[v] - depth[u];
        for(int j=0;j<LOG_V_MAX;++j) {
            if(depth_diff & (1 << j)) {
                v = parent[v][j];
            }
        }
        if(u == v) return u;
        for(int j=LOG_V_MAX-1;j>=0;--j) {
            if(parent[u][j] != parent[v][j]) {
                u = parent[u][j];
                v = parent[v][j];
            }
        }
        return parent[u][0];
    }
};

void dfs(int node, int par, ll dist, map<ll, int> &cmp, map<ll, ll> &dmp) {
    dists[node] = dist;
    for(int color: required_colors[node]) {
        colormp[V_MAX*node+color] = cmp[color];
        distmp[V_MAX*node+color] = dmp[color];
    }
    int chi, color; ll di;
    for(auto child: graph[node]) {
        tie(chi, color, di) = child;
        if(chi == par) continue;
        dist += di;
        ++cmp[color];
        dmp[color] += di;
        dfs(chi, node, dist, cmp, dmp);
        dist -= di;
        --cmp[color];
        dmp[color] -= di;
    }
}

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

    LowestCommonAncestor lca = LowestCommonAncestor(0, n);

    vector<tuple<int,ll,int,int,int>> query(q);
    int u,v,l,x; ll y;
    for(int i=0;i<q;++i) {
        cin >> x >> y >> u >> v;
        --x; --u; --v;
        l = lca.get_lca(u, v);
        query[i] = make_tuple(x, y, u, v, l);
        required_colors[u].insert(x);
        required_colors[v].insert(x);
        required_colors[l].insert(x);
    }

    {
        map<ll, int> mp1;
        map<ll, ll> mp2;
        dfs(0, -1, 0, mp1, mp2);
    }

    for(int i=0;i<q;++i) {
        tie(x, y, u, v, l) = query[i];
        ll ans = (dists[u]+dists[v]-2*dists[l]) - (distmp[V_MAX*u+x]+distmp[V_MAX*v+x]-2*distmp[V_MAX*l+x]) + y*(colormp[V_MAX*u+x]+colormp[V_MAX*v+x]-2*colormp[V_MAX*l+x]);
        cout << ans << endl;
    }
}

Measured memory_bytes: 85108