#include <cstdio>
#include <cctype>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;

#define ll long long
#define reg register
#define rep(i, a, b) for (reg int i = (a), i##end = (b); i <= i##end; ++i)
#define dep(i, a, b) for (reg int i = (a), i##end = (b); i >= i##end; --i)

template <typename _typer> inline _typer read() {
	_typer init = 0;
	char ch = getchar(), k = 0;
	for ( ; !isdigit(ch); ch = getchar()) k = (ch == '-');
	for ( ; isdigit(ch); ch = getchar())
		init = (init << 3) + (init << 1) + (ch ^ 48);
	return k ? -init : init;
}
const ll N = 100005, INF = 1e9;
const ll LogN = 20, M = N * LogN;

/*******************************************************************************
 *
 * FunctionalSegmentTree
 *
 ******************************************************************************/

int n, m;
struct EDGE {
	int to, nex, cost, col;
} edge[N << 1];
int head[N], cntedge;
void Addedge(int u, int v, int w, int c) {
	edge[++cntedge] = (EDGE) { v, head[u], w, c };
	head[u] = cntedge;
}

int Rt[N], Lson[M], Rson[M], cntNode;
int Sum[M], Tot[M];
void Insert(int &rt, int pre, int l, int r, int x, int d) {
	Sum[rt = ++cntNode] = Sum[pre] + d;
	Tot[rt] = Tot[pre] + 1;
	Lson[rt] = Lson[pre], Rson[rt] = Rson[pre];
	if (l == r) return ;
	int mid = (l + r) >> 1;
	if (x <= mid)
		Insert(Lson[rt], Lson[pre], l, mid, x, d);
	else Insert(Rson[rt], Rson[pre], mid + 1, r, x, d);
}
int res1, res2;
void Query(int a, int b, int c, int l, int r, int x) {
	if (l == r) {
		res1 += Sum[a] + Sum[b] - Sum[c] * 2;
		res2 += Tot[a] + Tot[b] - Tot[c] * 2;
		return ;
	}
	int mid = (l + r) >> 1;
	if (x <= mid)
		Query(Lson[a], Lson[b], Lson[c], l, mid, x);
	else Query(Rson[a], Rson[b], Rson[c], mid + 1, r, x);
}

int Dep[N], Fa[N];
int Siz[N], Son[N], Top[N], W[N];
void Dfs1(int u, int f, int c, int w) {
	if (u != 1)
		Insert(Rt[u], Rt[f], 1, n, c, w);
	Fa[u] = f;
	W[u] = W[f] + w, Dep[u] = Dep[f] + 1;
	Siz[u] = 1, Son[u] = -1;
	for (int i = head[u], v; i; i = edge[i].nex) {
		v = edge[i].to;
		if (v == f) continue;
		Dfs1(v, u, edge[i].col, edge[i].cost);
		Siz[u] += Siz[v];
		if (Son[u] == -1 || Siz[v] > Siz[Son[u]]) Son[u] = v;
	}
}
void Dfs2(int u, int tp) {
	Top[u] = tp;
	// if (u == 5) cout << Top[u] << endl;
	if (Son[u] != -1) Dfs2(Son[u], tp);
	for (int i = head[u], v; i; i = edge[i].nex) {
		v = edge[i].to;
		if (v == Fa[u] || v == Son[u]) continue;
		Dfs2(v, v);
	}
}
int Lca(int x, int y) {
	for ( ; Top[x] != Top[y]; y = Fa[Top[y]]) {
		if (Dep[Top[x]] > Dep[Top[y]]) swap(x, y);
		// cout << x << " " << y << " " << Top[x] << " " << Top[y] << endl;
	}
	return Dep[x] < Dep[y] ? x : y;
}

int Query(int x, int y, int c, int d) {
	int t = Lca(x, y);
	// cout << x << " " << y << " " << t << endl;
	int Ans = W[x] + W[y] - W[t] * 2;
	res1 = res2 = 0;
	Query(Rt[x], Rt[y], Rt[t], 1, n, c);
	Ans = Ans - res1 + res2 * d;
	return Ans;
}

int main() {
	n = read<int>(), m = read<int>();
	rep (i, 2, n) {
		int x = read<int>(), y = read<int>();
		int c = read<int>(), d = read<int>();
		Addedge(x, y, d, c);
		Addedge(y, x, d, c);
	}
	Dfs1(1, 1, 0, 0); Dfs2(1, 1);

	rep (i, 1, m) {
		int c = read<int>(), d = read<int>();
		int x = read<int>(), y = read<int>();
		printf("%d\n", Query(x, y, c, d));
	}
	return 0;
}



Measured memory_bytes: 41856