#include <cstdio>
#include <iostream>
#include <string>
#include <vector>
#include <sstream>
#include <map>
#include <set>
#include <queue>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <typeinfo>
#include <numeric>
#include <functional>
#include <unordered_map>
#include <bitset>
#include <stack>
#include <assert.h>
#include <unordered_set>
#include <random>


using namespace std;
using ll = long long;
using ull = unsigned long long;

const ll INF = 1e18;
const ll MOD = 1e9 + 7;

#define REP(i, n) for(ll i = 0; i < n; i++)



















using ll = long long;

class LCA {
    ll n, log_n;
    vector<vector<pair<ll, ll>>> parent;
    vector<ll> depth;
    vector<bool> used;
    
private:
    void dfs(const vector<vector<pair<ll, ll>>> &g, ll now, ll par, ll d, ll cost){
        parent[0][now].first = par;
        parent[0][now].second = cost;
        depth[now] = d;
        used[now] = true;
        
        for(auto &edge : g[now]){
            ll child = edge.first, c = edge.second;
            if(child != par){
                dfs(g, child, now, d + 1, c);
            }
        }
    }
    
public:
    LCA(const vector<vector<pair<ll, ll>>> &g) : n(g.size()), log_n(0), depth(n), used(n) {
        for(ll v = n; v > 0; v /= 2){
            log_n++;
        }
        parent.resize(log_n, vector<pair<ll, ll>>(n));
        for(ll i = 0; i < n; i++){
            if(!used[i]){
                dfs(g, i, -1, 0, 0);
            }
        }
        for(ll k = 0; k < log_n - 1; k++){
            for(ll v = 0; v < n; v++){
                if(parent[k][v].first < 0){
                    parent[k + 1][v] = parent[k][v];
                }
                else{
                    parent[k + 1][v].first = parent[k][parent[k][v].first].first;
                    parent[k + 1][v].second = max(parent[k][v].second, parent[k][parent[k][v].first].second);
                }
            }
        }
    }
    
    ll query(ll u, ll v){
        if(depth[u] > depth[v]){
            swap(u, v);
        }
        ll res = 0;
        for(ll k = 0; k < log_n; k++){
            if(((depth[v] - depth[u]) >> k) & 1){
                res = max(res, parent[k][v].second);
                v = parent[k][v].first;
            }
        }
        if(u == v){
            return res;
        }
        for(ll k = log_n - 1; k >= 0; k--){
            if(parent[k][u] != parent[k][v]){
                res = max(res, parent[k][u].second);
                res = max(res, parent[k][v].second);
                u = parent[k][u].first;
                v = parent[k][v].first;
            }
        }
        return res;
    }
    
    ll get_lca(ll u, ll v){
        if(depth[u] > depth[v]){
            swap(u, v);
        }
        for(ll k = 0; k < log_n; k++){
            if(((depth[v] - depth[u]) >> k) & 1){
                v = parent[k][v].first;
            }
        }
        if(u == v){
            return v;
        }
        for(ll k = log_n - 1; k >= 0; k--){
            if(parent[k][u].first != parent[k][v].first){
                u = parent[k][u].first;
                v = parent[k][v].first;
            }
        }
        return parent[0][v].first;
    }
};

int main(){
    ll n, q;
    cin >> n >> q;
    vector<vector<pair<ll, pair<ll, ll>>>> g(n);
    vector<vector<pair<ll, ll>>> g2(n);
    REP(i, n - 1){
        ll a, b, c, d;
        cin >> a >> b >> c >> d;
        a--; b--; c--;
        g[a].push_back({b, {c, d}});
        g[b].push_back({a, {c, d}});
        g2[a].push_back({b, 1});
        g2[b].push_back({a, 1});
    }
    LCA lca(g2);
    struct query {
        ll x, y, u, v, l;
    };
    vector<query> vec(q);
    vector<set<ll>> required_colors(n);
    REP(i, q){
        ll x, y, u, v;
        cin >> x >> y >> u >> v;
        x--; u--; v--;
        ll l = lca.get_lca(u, v);
        vec[i] = {x, y, u, v, l};
        required_colors[u].insert(x);
        required_colors[v].insert(x);
        required_colors[l].insert(x);
    }
    vector<ll> dist(n);
    map<ll, ll> colormp, distmp, cmp, dmp;
    [dfs = [&](auto &&dfs, ll now, ll par, ll d) -> void {
        dist[now] = d;
        for(auto &c : required_colors[now]){
            colormp[n * now + c] = cmp[c];
            distmp[n * now + c] = dmp[c];
        }
        for(auto &tmp : g[now]){
            ll ch = tmp.first, c = tmp.second.first, di = tmp.second.second;
            if(ch == par) continue;
            d += di;
            cmp[c]++;
            dmp[c] += di;
            dfs(dfs, ch, now, d);
            dmp[c] -= di;
            cmp[c]--;
            d -= di;
        }
    }](){ dfs(dfs, 0, -1, 0); }();
    REP(i, q){
        ll x = vec[i].x, y = vec[i].y, u = vec[i].u, v = vec[i].v, l = vec[i].l;
        ll ans = (dist[u] + dist[v] - 2 * dist[l])
                    - (distmp[n * u + x] + distmp[n * v + x] - 2 * distmp[n * l + x])
                    + y * (colormp[n * u + x] + colormp[n * v + x] - 2 * colormp[n * l + x]);
        cout << ans << endl;
    }
}

Measured memory_bytes: 107276