#include <iostream>
#include <map>
#include <vector>
#include <algorithm>
#include <map>
#include <string>
#include <queue>
#include <set>
#include <math.h>
using namespace std;
typedef long long ll;
typedef pair<ll, ll> P;
typedef pair<ll, P> Q;
const ll mod = 1000000007;
const ll INF = 1000000000000000;

ll n, q, a[100010], b[100010], c[100010], d[100010], depth[100010];
vector<ll> road[100010];
bool flg[100010];
ll parent[30][100010], len[100010], col[100010];
ll X[100010], Y[100010], u[100010], v[100010], lca[100010];
ll hon[100010], sum, irosum[100010], honsu[3][100010], naga[3][100010];
ll amo, pow_2[30];

ll na[100010];
vector<ll> honsuu, nagaa;
vector<Q> iro[100010];
vector<P> onsu, aga;


ll pow_mod(ll x, ll y)
{
	ll res = 1;
	while (y > 0)
	{
		if (y % 2 == 1)
		{
			(res *= x) %= mod;
		}
		(x *= x) %= mod;
		y /= 2;
	}
	return res;
}

ll div(ll x)
{
	return pow_mod(x, mod - 2);
}

void dfs(ll x, ll y)
{
	flg[x] = true;
	depth[x] = y;
	for (int i = 0; i < road[x].size(); i++)
	{
		if (flg[road[x][i]])
		{
			parent[0][x] = road[x][i];
		}
		else
		{
			dfs(road[x][i], y + 1);
		}
	}
}

void DFS(ll x)
{
	flg[x] = true;
	for (int i = 0; i < iro[x].size(); i++)
	{
		honsu[iro[x][i].second.second][iro[x][i].second.first] = hon[iro[x][i].first];
		naga[iro[x][i].second.second][iro[x][i].second.first] = irosum[iro[x][i].first];
		amo++;
	}
	na[x] = sum;
	for (int i = 0; i < road[x].size(); i++)
	{
		if (flg[road[x][i]]) continue;

		sum += len[road[x][i]];
		hon[col[road[x][i]]]++;
		irosum[col[road[x][i]]] += len[road[x][i]];

		DFS(road[x][i]);
	}
	sum -= len[x];
	hon[col[x]]--;
	irosum[col[x]] -= len[x];
}

bool jud(ll x, ll p, ll q)
{
	ll P = depth[p] - x, Q = depth[q] - x;
	
	ll t = 22;
	while (P > 0)
	{
		if (P >= pow_2[t])
		{
			p = parent[t][p];
			P -= pow_2[t];
		}
		t--;
	}

	t = 22;

	while (Q > 0)
	{
		if (Q >= pow_2[t])
		{
			q = parent[t][q];
			Q -= pow_2[t];
		}
		t--;
	}

	return p == q;
}

int main(void)
{
	cin >> n >> q;

	pow_2[0] = 1;
	for (int i = 1; i < 25; i++)
	{
		pow_2[i] = 2 * pow_2[i - 1];
	}

	for (int i = 1; i < n; i++)
	{
		cin >> a[i] >> b[i] >> c[i] >> d[i];
		road[a[i]].push_back(b[i]);
		road[b[i]].push_back(a[i]);
	}
	
	dfs(1, 0);
	
	for (int i = 1; i < n; i++)
	{
		ll p = (depth[a[i]] > depth[b[i]] ? a[i] : b[i]);
		col[p] = c[i], len[p] = d[i];
	}

	for (int i = 1; i < 20; i++)
	{
		for (int j = 1; j <= n; j++)
		{
			parent[i][j] = parent[i - 1][parent[i - 1][j]];
		}
	}
	
	for (int i = 0; i < q; i++)
	{
		cin >> X[i] >> Y[i] >> u[i] >> v[i];
		iro[u[i]].push_back({ X[i], {i, 0} });
		iro[v[i]].push_back({ X[i], {i, 1} });

		ll lb = 0, ub = min(depth[u[i]], depth[v[i]]);

		while (lb + 1 < ub)
		{
			ll mid = (lb + ub) / 2;
			if (jud(mid, u[i], v[i]))
			{
				lb = mid;
			}
			else
			{
				ub = mid;
			}
		}

		if (jud(ub, u[i], v[i]))
		{
			lb = ub;
		}

		ll R = depth[u[i]] - lb;
		lca[i] = u[i];
		ll t = 22;
		while (R > 0)
		{
			if (R >= pow_2[t])
			{
				lca[i] = parent[t][lca[i]];
				R -= pow(2, t);
			}
			t--;
		}
		iro[lca[i]].push_back({ X[i], {i, 2} });
	}

	for (int i = 1; i <= n; i++)
	{
		flg[i] = false;
	}

	DFS(1);

	for (int i = 0; i < q; i++)
	{
		ll ans = 0;
		ans += na[u[i]] - naga[0][i] + Y[i] * honsu[0][i];
		ans += na[v[i]] - naga[1][i] + Y[i] * honsu[1][i];
		ans -= 2 * (na[lca[i]] - naga[2][i] + Y[i] * honsu[2][i]);
		cout << ans << endl;
	}

	int www;
	cin >> www;
}


Measured memory_bytes: 55916