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

struct LCA {
    static const int BITLEN_MAX = 31;
    vector<int> parent[BITLEN_MAX];
    vector<int> depth;
    int bitlen;  // (1 << (bitlen - 1)) < N <= (1 << bitlen)

    void init(int N, const vector<vector<int>> &edges) {
        int root = 0;
        bitlen = 1;
        while((1 << bitlen) < N) ++bitlen;
        for(int i = 0; i < bitlen; ++i) parent[i].resize(N);
        depth.resize(N, -1);

        dfs(root, -1, 0, edges);
        for(int k = 0; k + 1 < bitlen; ++k) {
            for(int v = 0; v < N; ++v) {
                if(depth[v] == -1) continue;
                if(parent[k][v] < 0) {
                    parent[k + 1][v] = -1;
                } else {
                    parent[k + 1][v] = parent[k][parent[k][v]];
                }
            }
        }
    }

    void dfs(int v, int p, int d, const vector<vector<int>> &edges) {
        parent[0][v] = p;
        depth[v] = d;
        for(int u : edges[v]) {
            if(u != p) dfs(u, v, d + 1, edges);
        }
    }

    int query_lca(int u, int v) {
        if(depth[u] > depth[v]) swap(u, v);
        for(int k = 0; k < bitlen; ++k) {
            if(((depth[v] - depth[u]) >> k) & 1) v = parent[k][v];
        }
        if(u == v) return u;
        for(int k = bitlen - 1; k >= 0; --k) {
            if(parent[k][u] != parent[k][v]) {
                u = parent[k][u];
                v = parent[k][v];
            }
        }
        return parent[0][u];
    }

    int query_dist(int u, int v) {
        int l = query_lca(u, v);
        return depth[u] + depth[v] - 2 * depth[l];
    }
};

using tup = tuple<int, int, int>;
vector<vector<tup>> edges;
vector<vector<int>> edges_for_lca;
vector<int> dist;

vector<int> need[100000];
map<int, int> color_num[100000], color_sum[100000];
int cur_num[100000] = {}, cur_sum[100000] = {};

void dfs(int v, int p, int dis) {
    dist[v] = dis;
    for(int c : need[v]) {
        color_num[v][c] = cur_num[c];
        color_sum[v][c] = cur_sum[c];
    }

    for(tup t : edges[v]) {
        int u = get<0>(t), c = get<1>(t), d = get<2>(t);
        if(u == p) continue;
        cur_num[c] += 1;
        cur_sum[c] += d;
        dfs(u, v, dis + d);
        cur_num[c] -= 1;
        cur_sum[c] -= d;
    }
}

int main() {
    int N, Q;
    cin >> N >> Q;
    edges.resize(N);
    edges_for_lca.resize(N);
    dist.resize(N);
    for(int i=0; i<N-1; ++i) {
        int a, b, c, d;
        cin >> a >> b >> c >> d;
        --a; --b;
        edges[a].push_back(make_tuple(b, c, d));
        edges[b].push_back(make_tuple(a, c, d));
        edges_for_lca[a].push_back(b);
        edges_for_lca[b].push_back(a);
    }

    LCA lca;
    lca.init(N, edges_for_lca);

    vector<int> X(Q), Y(Q), U(Q), V(Q), L(Q);
    for(int i=0; i<Q; ++i) {
        cin >> X[i] >> Y[i] >> U[i] >> V[i];
        --U[i]; --V[i];
        L[i] = lca.query_lca(U[i], V[i]);
        need[U[i]].push_back(X[i]);
        need[V[i]].push_back(X[i]);
        need[L[i]].push_back(X[i]);
    }

    dfs(0, -1, 0);
    for(int i=0; i<Q; ++i) {
        int x = X[i], y = Y[i], u = U[i], v = V[i], l = L[i];
        int du = dist[u] - color_sum[u][x] + y * color_num[u][x];
        int dv = dist[v] - color_sum[v][x] + y * color_num[v][x];
        int dl = dist[l] - color_sum[l][x] + y * color_num[l][x];
        cout << du + dv - 2 * dl << endl;
    }
}

Measured memory_bytes: 64952