#include<vector>
#include<map>
#include<algorithm>
#include<set>
#include<iostream>
#include<string>
#include<set>
#include<queue>
#include<random>
//#include<unordered_set>

using namespace std;

/*
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>

using namespace __gnu_pbds;

tree<int, null_type, less<int>, rb_tree_tag, tree_order_statistics_node_update> st;*/

#pragma GCC optimize("Ofast")
#pragma GCC optimize("fast-math")
#pragma GCC optimize("unroll-loops")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,tune=native")

#define pb push_back
#define ld long double
#define int long long

mt19937 rnd(51);

const int N = 1e5 + 10;
vector<pair<int, pair<int,int>>> g[N];
vector<map<int, pair<int, int>>> mp(N);
vector<int> ans;
vector<bool> used(N);
vector<int> ind(N);
vector<int> d(N);
vector<pair<int, int>> t(8 * N, {1e18, 1e18});
vector<set<int>> color(N);
vector<int> num(N);
vector<int> cnt(N);
vector<int> dl(N);

void dfs(int v){
    used[v] = 1;
    ind[v] = ans.size();
    ans.pb(v);
    for (auto to : g[v]){
        if (!used[to.first]){
            d[to.first] = d[v] + 1;
            dl[to.first] = dl[v] + to.second.second;
            dfs(to.first);
            ans.pb(v);
        }
    }
}

void build(int v, int l, int r){
    if (l == r){
        t[v] = {d[ans[l]], ans[l]};
        return;
    }
    int m = (l + r) / 2;
    build(2 * v, l, m), build(2 * v + 1, m + 1, r);
    t[v] = min(t[v * 2], t[v * 2 + 1]);
}

pair<int, int> mn(int v, int tl, int tr, int l, int r){
    if (l > r){
        return {1e18, 1e18};
    }
    if (tl == l && tr == r){
        return t[v];
    }
    int tm = (tl + tr) / 2;
    return min(mn(2 * v, tl, tm, l, min(r, tm)), mn(2 * v + 1, tm + 1, tr, max(l, tm + 1), r));
}

void zfhs(int v){
    used[v] = 1;
    for (auto to : g[v]){
        if (!used[to.first]){
            num[to.second.first] += to.second.second;
            cnt[to.second.first]++;
            zfhs(to.first);
            cnt[to.second.first]--;
            num[to.second.first] -= to.second.second;
        }
    }
    for (auto to : color[v]){
        mp[v][to] = {num[to], cnt[to]};
    }
}

int32_t main()
{
	ios_base::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	vector<pair<pair<int, int>, pair<int,int>>> kek;
	vector<int> lol;
	int n, q;
	cin >> n >> q;
	for (int i = 0; i < n - 1; i++){
        int a, b, c, d;
        cin >> a >> b >> c >> d;
        g[a].pb({b, {c, d}});
        g[b].pb({a, {c, d}});
	}
	dfs(1);
	build(1, 0, ans.size() - 1);
	for (int i = 0; i < q; i++){
        int x, y, u, v;
        cin >> x >> y >> u >> v;
        int g = mn(1, 0, ans.size() - 1, min(ind[u], ind[v]), max(ind[u], ind[v])).second;
        color[g].insert(x);
        color[u].insert(x);
        color[v].insert(x);
        kek.pb({{x, y}, {u, v}});
        lol.pb(g);
	}
	fill(used.begin(), used.end(), 0);
	zfhs(1);
	for (int i = 0; i < kek.size(); i++){
        auto to = kek[i];
        int u = kek[i].second.first, v = kek[i].second.second, g = lol[i];
        int mx = dl[u] + dl[v] - 2 * dl[g];
        mx -= mp[u][to.first.first].first + mp[v][to.first.first].first - 2 * mp[g][to.first.first].first;
        mx += (mp[u][to.first.first].second + mp[v][to.first.first].second - 2 * mp[g][to.first.first].second) * kek[i].first.second;
        cout << mx << endl;
	}
	return 0;
}


Measured memory_bytes: 71468