#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define db double
#define pii pair<int,int>
#define pli pair<ll,int>
#define pil pair<int,ll>
#define pll pair<ll,ll>
const int inf = 1 << 30;
const ll linf = 1e18;
template<class T> void chmin(T& x, T y){if(x > y) x = y;}
template<class T> void chmax(T& x, T y){if(x < y) x = y;}

struct lca{
    //0-indexed
    int N;
    int logn;
    vector<vector<int>> G;
    vector<vector<int>> par;
    vector<int> depth;

    lca(int n) : N(n), logn(0), G(n), depth(n) {
        while((1 << logn) < N) logn++;
        par = vector<vector<int>>(logn, vector<int>(n));
    }

    void add_edge(int u, int v){
        G[u].push_back(v);
        G[v].push_back(u);
    }

    void dfs(int v, int p, int d){
        par[0][v] = p;
        depth[v] = d;

        for(auto& u : G[v]){
            if(p == u) continue;
            dfs(u, v, d + 1);
        }
    }

    void setting(){
        dfs(0, -1, 0);
        for(int i = 1; i < logn; i++){
            for(int j = 0; j < N; j++){
                if(par[i - 1][j] < 0) par[i][j] = -1;
                else par[i][j] = par[i - 1][par[i - 1][j]];
            }
        }
    }

    int get_lca(int u, int v){
        if(depth[u] < depth[v]) swap(u, v);
        int d = depth[u] - depth[v];

        for(int i = 0; i < logn; i++){
            if(d >> i & 1) u = par[i][u];
        }
        if(u == v) return u;

        for(int i = logn - 1; i >= 0; i--){
            if(par[i][u] != par[i][v]){
                u = par[i][u];
                v = par[i][v];
            }
        }
        return par[0][u];
    }
};

struct query{
    int col, dist, q, coe;
    query(int col, int dist, int q, int coe) : col(col), dist(dist), q(q), coe(coe) {}
};

struct edge{
    int to, col, dist;
    edge(int to, int col, int dist) : to(to), col(col), dist(dist) {}
};


int N, Q;
int cnt[100010];
int sum[100010];
int dist[100010];
int ans[100010];
vector<query> qs[100010];
vector<edge> G[100010];

void dfs(int v, int p, int di){
    dist[v] = di;
    for(auto u : G[v]){
        if(u.to == p) continue;
        dfs(u.to , v, di + u.dist);
    }
}

void dfs2(int v, int p){
    for(auto u : qs[v]){
        ans[u.q] += (cnt[u.col] * u.dist - sum[u.col]) * u.coe;  
    }

    for(auto u : G[v]){
        if(u.to == p) continue;
        cnt[u.col]++;
        sum[u.col] += u.dist;
        dfs2(u.to , v);
        cnt[u.col]--;
        sum[u.col] -= u.dist;

    }
}

int main(){
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    cin >> N >> Q;
    lca tree(N);
    for(int i = 1; i < N; i++){
        int a, b, c, d;
        cin >> a >> b >> c >> d;
        a--, b--;
        tree.add_edge(a, b);
        G[a].emplace_back(b, c, d);
        G[b].emplace_back(a, c, d);
    }
    tree.setting();
    dfs(0, -1, 0);

    for(int i = 0; i < Q; i++){
        int x, y, u, v;
        cin >> x >> y >> u >> v;
        u--, v--;
        int c = tree.get_lca(u, v);
        qs[u].emplace_back(x, y, i, 1);
        qs[v].emplace_back(x, y, i, 1);
        qs[c].emplace_back(x, y, i, -2);
        ans[i] += dist[u] + dist[v] - (dist[c] * 2);
    }
    dfs2(0, -1);
    for(int i = 0; i < Q; i++) cout << ans[i] << endl;
    return 0;
}

Measured memory_bytes: 34548