#define _CRT_SECURE_NO_WARNINGS
#pragma comment(linker, "/stack:256000000")
#include<utility>
#include<iostream>
#include<vector>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<ctime>
#include<functional>
#include<random>
#include<climits>
#include<queue>
#include<stack>
#include<deque>
#include<bitset>
#include<map>
#include<set>
#include<unordered_map>
#include<unordered_set>
#include<cassert>
#include<ccomplex>

//4Head
#define all(x) x.begin(), x.end()
#define mp make_pair
#define X first
#define Y second

using namespace std;
using ll = long long;
using ull = unsigned long long;
using ld = long double;
mt19937_64 gen(time(NULL));

// belik's shit
ll const mod = 1e9 + 7;
namespace {
	ll mult(ll a, ll b) {
		ll val = a * b - (ll)((ld)a * b / mod) * mod;
		if (val < 0) {
			val += mod;
		}
		if (val >= mod) {
			val -= mod;
		}
		return val;
	}
	ll poww(ll a, ll b)
	{
		ll val = 1;
		a %= mod;
		while (b > 0){
			if (b % 2) val = mult(a, val);
			a = mult(a, a);
			b >>= 1;
		}
		return val % mod;
	}
	ll inv(ll a) {
		return poww(a, mod - 2);
	}
}

ll const maxn = 5e5 + 5;
ll const maxc = 30;

ll up[maxn][maxc];

struct edge {
	ll to, c, d;
};
vector<edge>g[maxn];
bool used[maxn];
ll tin[maxn], tout[maxn];
ll timer = 0;
void dfs(ll u, ll p) {
	tin[u] = timer++;
	used[u] = 1;
	up[u][0] = p;
	for (ll i = 1; i < maxc; i++) {
		up[u][i] = up[up[u][i - 1]][i - 1];
	}
	for (auto e : g[u]) {
		if (used[e.to]) continue;
		dfs(e.to, u);
	}
	tout[u] = timer++;
}
bool is_predok(ll u, ll v) {
	return (tin[u] <= tin[v] && tin[v] <= tout[u]);
}
ll lca(ll a, ll b) {
	ll u = a; if (is_predok(a, b)) return a;
	for (ll i = maxc - 1; i >= 0; i--) {
		if (!is_predok(up[u][i], b)) {
			u = up[u][i];
		}
	}
	return up[u][0];
}
map<pair<ll, ll>, pair<ll,ll>> mapa; // {vert, color} -> {dlina_color, cnt_color}
unordered_set<ll> useful_cols[maxn];
ll dlina = 0;
ll d[maxn];
ll cnt_colors[maxn];
ll d_colors[maxn];

void dfs1(ll u, ll col, ll dlina_rebra) {
	used[u] = 1;
	for (auto col : useful_cols[u]) {
		mapa[mp(u, col)] = { d_colors[col], cnt_colors[col] };
	}
	d[u] = dlina;
	for (auto e : g[u]) {
		if (used[e.to]) continue;
		dlina += e.d;
		cnt_colors[e.c]++;
		d_colors[e.c] += e.d;
		dfs1(e.to, e.c, e.d);
	}
	if (col != -1) {
		cnt_colors[col]--;
		d_colors[col] -= dlina_rebra;
		dlina -= dlina_rebra;
	}
}

signed main() {
	ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
	ll n, q; cin >> n >> q;
	for (ll i = 0; i < n - 1; i++) {
		ll a, b, c, d; cin >> a >> b >> c >> d;
		g[a].push_back({ b,c,d });
		g[b].push_back({ a,c,d });
	}
	ll root = 1;
	dfs(root, root);
	fill_n(used, maxn, 0);
	vector<ll>x(q), y(q), u(q), v(q);
	for (ll i = 0; i < q; i++) {
		cin >> x[i] >> y[i] >> u[i] >> v[i];
		useful_cols[u[i]].insert(x[i]); useful_cols[v[i]].insert(x[i]);
		useful_cols[lca(u[i], v[i])].insert(x[i]);
	}
	dfs1(root, -1, 0);
	for (ll i = 0; i < q; i++) {
		ll a = u[i], b = v[i], c = lca(u[i], v[i]);
		ll col = x[i], dl = y[i];
		ll st_dlina = d[a] + d[b] - 2 * d[c];
		ll cnt_colors = mapa[mp(a, col)].Y + mapa[mp(b, col)].Y - 2 * mapa[mp(c, col)].Y;
		ll dli_colors = mapa[mp(a, col)].X + mapa[mp(b, col)].X - 2 * mapa[mp(c, col)].X;
		ll ans = st_dlina - dli_colors + cnt_colors * dl;
		cout << ans << '\n';
	}

	return 0;
}
/*

*/

Measured memory_bytes: 127540