//author Eterna
#pragma GCC optimize(2)
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<string>
#include<cstring>
#include<vector>
#include<map>
#include<set>
#include<queue>
#include<stack>
#include<utility>
#include<cmath>
#include<climits>
#include<deque>
#include<functional>
#include<complex>
#include<numeric>
#define INF 0x7fffffff
#define Pi acos(-1.0)
#define lowbit(x) ((x) & (-(x)))
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pii;
const int maxn = 1e5;
inline int read_int() {
	char c;
	int ret = 0, sgn = 1;
	do { c = getchar(); } while ((c < '0' || c > '9') && c != '-');
	if (c == '-') sgn = -1; else ret = c - '0';
	while ((c = getchar()) >= '0' && c <= '9') ret = ret * 10 + (c - '0');
	return sgn * ret;
}
inline ll read_ll() {
	char c;
	ll ret = 0, sgn = 1;
	do { c = getchar(); } while ((c < '0' || c > '9') && c != '-');
	if (c == '-') sgn = -1; else ret = c - '0';
	while ((c = getchar()) >= '0' && c <= '9') ret = ret * 10 + (c - '0');
	return sgn * ret;
}
struct edge {
	int to, weight, next, col;
}e[2 * maxn + 5];
int Top[maxn + 5], parent[maxn + 5], Size[maxn + 5], deepth[maxn + 5], son[maxn + 5];
int ID[maxn + 4], Rank[maxn + 5], value[maxn + 5], tot;
int head[maxn + 5], cnt;
pii Edge[maxn + 5];
inline void Add_edge(int u, int v, int c, int weight) {
	e[++cnt].next = head[u]; e[cnt].to = v; e[cnt].col = c; e[cnt].weight = weight; head[u] = cnt;
	e[++cnt].next = head[v]; e[cnt].to = u; e[cnt].col = c; e[cnt].weight = weight; head[v] = cnt;
}
void DFS1(int now, int father, int deep) {
	parent[now] = father, deepth[now] = deep; Size[now] = 1;
	for (int i = head[now]; i; i = e[i].next) {
		int k = e[i].to;
		if (k != father) {
			value[k] = e[i].weight;
			DFS1(k, now, deep + 1);
			Size[now] += Size[k];
			if (son[now] == -1 || Size[k] > Size[son[now]])son[now] = k;
		}
	}
}
void DFS2(int now, int root) {
	Top[now] = root; ID[now] = ++tot;  Rank[tot] = now;
	if (son[now] == -1) return;
	DFS2(son[now], root);
	for (int i = head[now]; i; i = e[i].next) {
		int k = e[i].to;
		if (k != son[now] && k != parent[now])DFS2(k, k);
	}
}
struct Query {
	bool operator < (const Query& rhs)const {
		return c < rhs.c;
	}
	int c, d, u, v, id;
}Q[maxn + 5];
int n, q, res[maxn + 5];
int arr[2][maxn + 5], c[maxn + 5];
void add1(int id, int x, int v) {
	for (int i = x; i <= n; i += lowbit(i))arr[id][i] += v;
}
void add2(int x, int v) {
	for (int i = x; i <= n; i += lowbit(i))c[i] += v;
}
int sum1(int id, int x) {
	int res = 0;
	for (int i = x; i > 0; i -= lowbit(i))res += arr[id][i];
	return res;
}
int sum2(int x) {
	int res = 0;
	for (int i = x; i > 0; i -= lowbit(i))res += c[i];
	return res;
}
struct Node {
	Node(int _u, int _v, int _w) {
		u = _u, v = _v, w = _w;
	}
	int u, v, w;
};
vector<Node> color[maxn + 5];
int Query1(int id, int x, int y) {
	int res = 0;
	while (Top[x] != Top[y]) {
		if (deepth[Top[x]] < deepth[Top[y]])swap(x, y);
		int s = abs(sum1(id, ID[x]) - sum1(id, ID[Top[x]] - 1));
		res += s;
		x = parent[Top[x]];
	}
	if (deepth[x] > deepth[y])swap(x, y);
	int s = abs(sum1(id, ID[y]) - sum1(id, ID[x]));
	res += s;
	return res;
}
int Query2(int x, int y) {
	int res = 0;
	while (Top[x] != Top[y]) {
		if (deepth[Top[x]] < deepth[Top[y]])swap(x, y);
		int s = abs(sum2(ID[x]) - sum2(ID[Top[x]] - 1));
		res += s;
		x = parent[Top[x]];
	}
	if (deepth[x] > deepth[y])swap(x, y);
	int s = abs(sum2(ID[y]) - sum2(ID[x]));
	res += s;
	return res;
}
int main()
{
	n = read_int(), q = read_int();
	memset(son, -1, sizeof(son));
	for (int i = 1, u, v, c, w; i < n; ++i) {
		u = read_int(), v = read_int(), c = read_int(), w = read_int();
		Add_edge(u, v, c, w);
		color[c].push_back(Node(u, v, w));
	}
	for (int i = 1; i <= q; ++i) {
		Q[i].c = read_int(), Q[i].d = read_int(), Q[i].u = read_int(), Q[i].v = read_int();
		Q[i].id = i;
	}
	sort(Q + 1, Q + 1 + q);
	DFS1(1, 1, 1);
	DFS2(1, 1);
	for (int i = 1; i <= n; ++i)add1(0, i, value[Rank[i]]);
	int now = 0;
	for (int i = 1; i <= q; ++i) {
		if (Q[i].c != now) {
			for (auto eg : color[now]) {
				int u = eg.u, v = eg.v, w = eg.w;
				int pos = u;
				if (parent[v] == u)pos = v;
				add1(1, ID[pos], -w);
				add2(ID[pos], -1);
			}
			now = Q[i].c;
			for (auto eg : color[now]) {
				int u = eg.u, v = eg.v, w = eg.w;
				int pos = u;
				if (parent[v] == u)pos = v;
				add1(1, ID[pos], w);
				add2(ID[pos], 1);
			}
		}
		int ans = Query1(0, Q[i].u, Q[i].v) - Query1(1, Q[i].u, Q[i].v);
		int num = Query2(Q[i].u, Q[i].v);
		ans += num * Q[i].d;
		res[Q[i].id] = ans;
	}
	for (int i = 1; i <= q; ++i)printf("%d\n", res[i]);
	return 0;
}

Measured memory_bytes: 21688