#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp> // Common file
#include <ext/pb_ds/tree_policy.hpp> // Including tree_order_statistics_node_update
using namespace std;
using namespace __gnu_pbds;
typedef tree<int, null_type, less<int>, rb_tree_tag, tree_order_statistics_node_update> ordered_set;

class LCA { // 1-indexed
    void dfs(int v, int p = 0) {
        lca[0][v] = p;
        for(auto u: G[v]) if(u != p) {
            dis[u] = dis[v] + 1;
            dfs(u, v);
        }
    }
public:
    vector <vector<int>> lca;
    vector <int> dis;
    int N;
    vector <int> *G;
    void build(int N, vector <int> *G, int root = 1) {
        this->N = N;
        this->G = G;
        lca.emplace_back(N + 1, 0);
        dis.assign(N + 1, 0);
        dfs(root);
        for(int i = 1; (1 << i) <= N; i++) {
            lca.emplace_back(N + 1, 0);
            for(int v = 1; v <= N; v++)
                lca[i][v] = lca[i - 1][lca[i - 1][v]];
        }
    }
    int query(int p, int q) {
        int tmp, log;

        if(dis[p] < dis[q]) {
            tmp = p, p = q, q = tmp;
        }

        for(log = 1; 1 << log <= dis[p]; log++);
        log--;

        for(int i = log; i >= 0; i--)
            if(dis[p] - (1 << i) >= dis[q])
                p = lca[i][p];

        if (p == q)
            return p;

        for(int i = log; i >= 0; i--)
            if(lca[i][q] != -1 && lca[i][p] != lca[i][q])
                p = lca[i][p], q = lca[i][q];

        return lca[0][p];
    }
};

struct query {
    int u; int v; int lca;
    int color; int new_d;
    int u_d; int v_d; int lca_d;
};

int N, Q;
vector <int> G[100005];
vector <int> D[100005];
vector <int> C[100005];
vector <int> off[100005];
LCA lca;
query queries[100005];

int color_d[100005];
int color_cnt[100005];
int dista[100005];

void dfs(int v, int p = -1) {
    for(auto q: off[v]) {
        auto &query = queries[q];
        if(query.v == v) query.v_d = dista[v] - color_d[query.color] + color_cnt[query.color] * query.new_d;
        if(query.u == v) query.u_d = dista[v] - color_d[query.color] + color_cnt[query.color] * query.new_d;
        if(query.lca == v) query.lca_d = dista[v] - color_d[query.color] + color_cnt[query.color] * query.new_d;
    }

    for(int i = 0; i < G[v].size(); i++) if(G[v][i] != p) {
        dista[G[v][i]] = dista[v] + D[v][i];
        color_d[C[v][i]] += D[v][i];
        color_cnt[C[v][i]]++;
        dfs(G[v][i], v);
        color_d[C[v][i]] -= D[v][i];
        color_cnt[C[v][i]]--;
    }
}

int main() {
    ios_base::sync_with_stdio(false);
    cin >> N >> Q;
    for(int i = 1; i <= N - 1; i++) {
        int a, b, c, d;
        cin >> a >> b >> c >> d;
        G[a].push_back(b); D[a].push_back(d); C[a].push_back(c);
        G[b].push_back(a); D[b].push_back(d); C[b].push_back(c);
    }
    lca.build(N, G);
    for(int i = 1; i <= Q; i++) {
        int x, y, u, v;
        cin >> x >> y >> u >> v;
        queries[i].color = x;
        queries[i].new_d = y;
        queries[i].u = u;
        queries[i].v = v;
        queries[i].lca = lca.query(u, v);
        off[u].push_back(i);
        off[v].push_back(i);
        off[queries[i].lca].push_back(i);
    }
    dfs(1);
    for(int i = 1; i <= Q; i++) {
        cout << queries[i].u_d + queries[i].v_d - queries[i].lca_d * 2 << endl;
    }
}

Measured memory_bytes: 39804