#pragma GCC optimize("Ofast")
#include <bits/stdc++.h>
 
using namespace std;
 
typedef long long ll;
typedef long double ld;
typedef pair<int, int> pii;
typedef pair<ld, ld> pdd;

#define fi first
#define se second
#define mp make_pair
#define fastIO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);

const int N = (int)1e5 + 9;
const int LOG = 20;
int par[LOG][N];
ll dist[N];
int tin[N];
int tout[N];
int tt;

vector<pii> T[N];

void dfs(int u, int pr){
    par[0][u] = pr;
    tin[u] = ++tt;
    for(int i = 1; i < LOG; i ++ ){
        par[i][u] = par[i-1][par[i-1][u]];
    }
    for(auto x : T[u]){
        if(x.fi == pr)
            continue;
        dist[x.fi] = dist[u] + x.se;
        dfs(x.fi, u);
    }
    tout[u] = tt;
}

bool is(int a, int b){
    return tin[a] <= tin[b] && tout[a] >= tout[b];
}

int lca(int a, int b){
    if(is(a,b)) return a;
    if(is(b,a)) return b;
    for(int i = LOG - 1; i >= 0 ; i -- ){
        if(!is(par[i][a], b)){
            a = par[i][a];
        }
    }
    return par[0][a];
}

ll sum[N];
ll cs[N];
ll ti[N];

struct Edge{
    ll A;
    ll B;
    ll D;
};

struct Query{
    ll nd;
    ll u;
    ll v;
    ll id;
};


vector<Edge> P[N];
vector<Query> vv[N];

struct Node{
    ll value;
    ll lazy;
};

ll nw[N];
Node TR[N * 4 + 512];

void push(int node, int cl, int cr){
    TR[node].value += (cr - cl + 1) * 1ll * TR[node].lazy;    
    if(cl != cr){
        TR[node * 2].lazy += TR[node].lazy;
        TR[node * 2 + 1].lazy += TR[node].lazy;
    }
    TR[node].lazy =0 ;
}

void update(int node, int cl, int cr, int tl, int tr, ll v){
    push(node, cl, cr);
    if(cr < tl)
        return;
    if(cl > tr)
        return;
    if(cl >= tl && cr <= tr){
        TR[node].lazy = v;
        push(node, cl, cr);
        return;
    }
    int mid = (cl + cr) / 2;
    update(node * 2, cl, mid, tl, tr, v);
    update(node * 2 + 1, mid + 1, cr, tl, tr, v);
    TR[node].value = TR[node * 2].value + TR[node * 2 + 1].value;
}

int ask(int node, int cl, int cr, int ps){
    push(node, cl, cr);
    if(cl == cr)
        return TR[node].value;
    int mid = (cl + cr) / 2;
    if(mid >= ps)
        return ask(node * 2, cl, mid, ps);
    else
        return ask(node * 2 + 1, mid + 1, cr, ps);
}

int main(){
    fastIO;
    int n, q;
    cin >> n >> q;
    ll u, v, cl, d;
    for(int i = 1; i < n; i ++ ){
        cin >> u >> v >> cl >> d;
        T[u].push_back(mp(v,d));
        T[v].push_back(mp(u,d));
        P[cl].push_back({u, v, d});
    }
    dfs(1, 1);
    ll ci, di, x, y;
    for(int i = 0 ; i < q; i ++ ){
        cin >> ci >> di >> x >> y;
        sum[i] = dist[x] + dist[y] - 2ll * dist[lca(x,y)];
        vv[ci].push_back({di, x, y, i});
        nw[i] = di;
    }
    for(int i = 1; i < N; i ++ ){
        for(auto &x : P[i]){
            if(tin[x.A] > tin[x.B])
                swap(x.A,x.B);
        }
        for(auto x : P[i]){
            update(1, 1, n, tin[x.B], tout[x.B], +1);
        }
        for(auto x : vv[i]){
            cs[x.id] = ask(1, 1, n, tin[x.u]) + ask(1, 1, n, tin[x.v]) - 2ll * ask(1, 1, n, tin[lca(x.u,x.v)]);
        }
        for(auto x : P[i]){
            update(1, 1, n, tin[x.B], tout[x.B], -1);
        }
        for(auto x : P[i]){
            update(1, 1, n, tin[x.B], tout[x.B], x.D);
        }
        for(auto x : vv[i]){
            ti[x.id] = ask(1, 1, n, tin[x.u]) + ask(1, 1, n, tin[x.v]) - 2ll * ask(1, 1, n, tin[lca(x.u,x.v)]);
        }
        for(auto x : P[i]){
            update(1, 1, n, tin[x.B], tout[x.B], -x.D);
        }
        
    }
    for(int i = 0 ; i < q; i ++ ){
        cout << sum[i] - ti[i] + cs[i] * nw[i] << "\n";
    }
    return 0;
}


Measured memory_bytes: 39724