#include<bits/stdc++.h>
using namespace std;
const int maxm = 1e6 + 10;
const int maxn = 3e5+10;
typedef long long ll;
struct node {
	int s, e, c, w, next;
}edge[maxn];
int head[maxn], len;
int n, q;
void init() {
	memset(head, -1, sizeof(head));
	len = 0;
}
void add(int s, int e, int c, int w) {
	edge[len].s = s;
	edge[len].e = e;
	edge[len].w = w;
	edge[len].c = c;
	edge[len].next = head[s];
	head[s] = len++;
}
int son[maxn], top[maxn], tid[maxn], fat[maxn], siz[maxn], dep[maxn], rak[maxn];
int dfx;
void dfs1(int x, int fa, int d) {
	siz[x] = 1, son[x] = -1, fat[x] = fa, dep[x] = d;
	for (int i = head[x]; i != -1; i = edge[i].next) {
		int y = edge[i].e;
		if (y == fa)
			continue;
		dfs1(y, x, d + 1);
		siz[x] += siz[y];
		if (son[x] == -1 || siz[y] > siz[son[x]])
			son[x] = y;
	}
}
void dfs2(int x, int c) {
	top[x] = c; tid[x] = ++dfx; rak[dfx] = x;
	if (son[x] == -1)
		return;
	dfs2(son[x], c);
	for (int i = head[x]; i != -1; i = edge[i].next) {
		int y = edge[i].e;
		if (y == fat[x] || y == son[x])
			continue;
		dfs2(y, y);
	}
}
int cnt, root[maxn], ls[maxn * 40], rs[maxn * 40], num[maxn * 40], val[maxn * 40];
struct C {
	int color, dis;
}a[maxn];
void build(C k, int l, int r, int& i) {
	num[++cnt] = num[i] + 1, val[cnt] = val[i] + k.dis, ls[cnt] = ls[i], rs[cnt] = rs[i];
	i = cnt;
	if (l == r)
		return;
	int mid = l + r >> 1;
	if (k.color <= mid)
		build(k, l, mid, ls[i]);
	else
		build(k, mid + 1, r, rs[i]);
}
C query(int u, int v, int k, int l, int r) {
	if (l == r) {
		return { num[v] - num[u],val[v] - val[u] };
	}
		
	int mid = l + r >> 1;
	if (k <= mid)
		return query(ls[u], ls[v], k, l, mid);
	else
		return query(rs[u], rs[v], k, mid + 1, r);
}
int solve(int cr, int dis, int x, int y) {
	C ans = { 0,0 };
	int sum = 0;
	while (top[x] != top[y]) {
		if (dep[top[x]] < dep[top[y]])
			swap(x, y);
		C t = query(root[tid[top[x]] - 1], root[tid[x]], cr, 1, n);
		sum += val[root[tid[x]]] - val[root[tid[top[x]] - 1]];
		ans.color += t.color, ans.dis += t.dis;
		x = fat[top[x]];
	}
	
	if (x != y) {
		if (dep[x] < dep[y])
			swap(x, y);
		C t = query(root[tid[son[y]] - 1], root[tid[x]], cr, 1, n);
		sum += val[root[tid[x]]] - val[root[tid[son[y]] - 1]];
		ans.color += t.color, ans.dis += t.dis;
	}
	//cout << sum << " " << ans.color << " " << ans.dis << endl;
	return sum - ans.dis + ans.color * dis;
}
void dfs(int l, int r, int i) {
	if (l == r) {
		printf("%d#%d ", num[i], val[i]);
		return;
	}
	int mid = l + r >> 1;
	dfs(l, mid, ls[i]);
	dfs(mid + 1, r, rs[i]);
}
int main() {
	scanf("%d%d", &n, &q);
	init();
	for (int i = 1, x, y, c, d; i < n; i++) {
		scanf("%d%d%d%d", &x, &y, &c, &d);
		add(x, y, c, d);
		add(y, x, c, d);
	}
	dfs1(1, 0, 1);
	dfs2(1, 1);
	for (int i = 0; i < len; i += 2) {
		int x = edge[i].e;
		int y = edge[i].s;
		if (dep[x] < dep[y])
			swap(x, y);
		a[tid[x]] = { edge[i].c, edge[i].w };
	}
	for (int i = 2; i <= dfx; i++) {
		root[i] = root[i - 1];
		build(a[i], 1, n, root[i]);
		//dfs(1, n, root[i]);
	}
	while (q--) {
		int x, y, u, v;
		scanf("%d%d%d%d", &x, &y, &u, &v);
		printf("%d\n", solve(x, y, u, v));
	}
}