#include <bits/stdc++.h>
using namespace std;
using ll = long long;
ll INF = 1e9;

struct Edge {
    int to;
    int c;
    ll d;
};

struct DepLen {
    int dep;
    ll len;
};

vector<vector<Edge>> G;
vector<int> DEP; // rootからのdepth
vector<ll> DST; // rootからの距離
vector<map<int, DepLen>> CDST; // rootからの色別距離
vector<vector<int>> PA;
vector<int> X;
vector<ll> Y;
vector<int> U;
vector<int> V;

map<int, DepLen> t_cdst; // rootからの色別距離（作業用）

int lca(int u, int v) {
    if ( DEP[u] < DEP[v] ) swap(u, v);
    int dd = DEP[u] - DEP[v];
    for ( int k = PA.size()-1; k >= 0; k-- ) {
        if ( (dd >> k) & 1 ) {
            u = PA[k][u];
        }
    }
    if ( u == v ) return u;
    for ( int k = PA.size()-1; k >= 0; k-- ) {
        if ( PA[k][u] != PA[k][v] ) {
            u = PA[k][u];
            v = PA[k][v];
        }
    }
    return PA[0][u];
}

void dfs_init(int v, int p, int dep, ll len) {
    PA[0][v] = p;
    DEP[v] = dep;
    DST[v] = len;
    for ( auto e : G[v] ) {
        if ( e.to == p ) continue;
        dfs_init( e.to, v, dep + 1, len + e.d );
    }
    // PA[0][v] = p;
    // DEP[v] = dep;
    // DST[v] = len;
    // for ( auto& z : CDST[v] ) {
    //     z.second = t_cdst[z.first];
    // }
    // for ( auto e : G[v] ) {
    //     if ( e.to == p ) continue;
    //     t_cdst[e.c].dep += 1;
    //     t_cdst[e.c].len += e.d;
    //     dfs_init( e.to, v, dep + 1, len + e.d );
    //     t_cdst[e.c].dep -= 1;
    //     t_cdst[e.c].len -= e.d;
    // }
}

void dfs_dst(int v, int p) {
    for ( auto& z : CDST[v] ) {
        z.second = t_cdst[z.first];
    }
    for ( auto e : G[v] ) {
        if ( e.to == p ) continue;
        t_cdst[e.c].dep += 1;
        t_cdst[e.c].len += e.d;
        dfs_dst( e.to, v );
        t_cdst[e.c].dep -= 1;
        t_cdst[e.c].len -= e.d;
    }
}

int main() {
    ll N, Q;
    cin >> N >> Q;
    ll LOGN = (ll)(log(N) / log(2)) + 2;
    G.resize(N);
    DEP.resize(N, -1);
    DST.resize(N, INF);
    CDST.resize(N);
    PA.resize(LOGN, vector<int>(N, -1));
    ll a,b,c,d,x,y,u,v;
    for ( int i = 0; i < N-1; i++ ) {
        cin >> a >> b >> c >> d;
        a--, b--;
        G[a].push_back({b, c, d});
        G[b].push_back({a, c, d});
    }
    dfs_init(0, -1, 0, 0);

    X.resize(Q), Y.resize(Q), U.resize(Q), V.resize(Q);
    for ( int i = 0; i < Q; i++ ) {
        cin >> x >> y >> u >> v;
        u--, v--;
        X[i] = x;
        Y[i] = y;
        U[i] = u;
        V[i] = v;
        CDST[u][x] = DepLen{0,0};
        CDST[v][x] = DepLen{0,0};
        
    }

    for( int k = 1; k < LOGN; k++ ) {
        for ( int i = 0; i < N; i++ ) {
            if ( PA[k-1][i] != -1 ) {
                PA[k][i] = PA[k-1][PA[k-1][i]];
            } else {
                PA[k][i] = -1;
            }
        }
    }
    for ( int i = 0; i < Q; i++ ) {
        int a = lca(U[i], V[i]);
        CDST[a][X[i]] = DepLen{0,0};
    }
    dfs_dst(0, -1);

    for ( int q = 0; q < Q; q++ ) {
        int a = lca(U[q], V[q]);
        ll ans = DST[U[q]] + DST[V[q]] - 2 * DST[a];
        ans -= CDST[U[q]][X[q]].len + CDST[V[q]][X[q]].len - 2 * CDST[a][X[q]].len;
        ans += Y[q] * (CDST[U[q]][X[q]].dep + CDST[V[q]][X[q]].dep - 2 * CDST[a][X[q]].dep);
        cout << ans << "\n";
    }

    return 0;
}

Measured memory_bytes: 46068