#include <bits/stdc++.h>

#define ln                '\n'
#define all(dat)           dat.begin(), dat.end()
#define loop(i, to)        for (int i = 0; i < to; ++i)
#define cont(i, to)        for (int i = 1; i <= to; ++i)
#define circ(i, fm, to)    for (int i = fm; i <= to; ++i)
#define foreach(i, dat)    for (__typeof(dat.begin()) i = dat.begin(); i != dat.end(); ++i)

typedef long long          num;

using namespace std;

namespace io {
	const int bufsz = 1 << 24;
	static char buf[bufsz], puf[bufsz], *p1, *p2, *pp = puf;
	
	#define isdigit(c)  (c >= '0' && c <= '9')
	#define isalpha(c)  (c >= 'a' && c <= 'z')
	#define isAlpha(c)  (c >= 'A' && c <= 'Z')
	#define isalnum(c)  (isalpha(c) || isAlpha(c) || isdigit(c))
	#define getchar()   (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, bufsz, stdin), p1 == p2) ? EOF : *p1++)
	#define flush()     (fwrite(puf, 1, pp - puf, stdout), pp = puf)
	#define putchar(c)  (*pp++ = c, pp - puf == bufsz && flush())
	
	template<class type>
	void inline read(type &a) {
		int f = 1, c = getchar();
		for (; !isdigit(c); c == 45 && (f = -1), c = getchar());
		for (a = 0; isdigit(c); a *= 10, a += c & 15, c = getchar());
		a *= f;
	}
	
	void inline read_str(string &s) {
		char c = getchar();
		for (; !isalnum(c); c = getchar());
		for (s = ""; isalnum(c); s += c, c = getchar());
	}
	
	template<class type>
	void inline write(type a, char c = ln) {
		static char d[20];
		int s = d[0] = 0;
		for (a < 0 && (putchar(45), a = -a); a; d[s++] = a % 10, a /= 10);
		for (s || (s = 1); s; putchar(d[--s] + 48));
		putchar(c);
	}
	
	void inline write_str(string s, char c = ln) {
		loop (i, s.size()) {
			putchar(s[i]);
		}
		putchar(c);
	}
}
using namespace io;

const int nsz = 1e5;
int n, m, ans[nsz + 5];
int rt = 1, w[nsz + 5], c[nsz + 5], siz[nsz + 5], pr[nsz + 5], dep[nsz + 5], hs[nsz + 5], top[nsz + 5], id[nsz + 5];
vector<int> col[nsz + 5];

struct bianry_index_tree {
	int sum[nsz + 5];
	
	void inline upd(int u, int w) {
		for (; u <= n; sum[u] += w, u += u & -u);
	}
	
	int inline qry(int u) {
		int res = 0;
		for (; u > 0; res += sum[u], u -= u & -u);
		return res;
	}
	
	int inline qry(int l, int r) {
		return qry(r) - qry(l - 1);
	}
};
bianry_index_tree tr, sum, cnt;

struct graph {
	int sz, hd[nsz + 5];
	
	struct edge {
		int nxt, to, w, c;
		
		edge(int nxt = 0, int to = 0, int w = 0, int c = 0) {
			this->nxt = nxt, this->to = to, this->w = w, this->c = c;
		}
	};
	edge e[2 * nsz + 5];
	
	inline edge& operator [] (int id) { return e[id]; }
	
	void inline link(int u, int v, int w = 0, int c = 0) {
		e[++sz] = edge(hd[u], v, w, c), hd[u] = sz;
		e[++sz] = edge(hd[v], u, w, c), hd[v] = sz;
	}
};
graph g;

struct query {
	int id, u, v, c, w;
	
	query(int id = 0, int u = 0, int v = 0, int w = 0, int c = 0) {
		this->id = id, this->u = u, this->v = v, this->w = w, this->c = c;
	}
};
vector<query> qy[nsz + 5];

void dfs1(int u = rt) {
	siz[u] = 1;
	for (int i = g.hd[u]; i; i = g[i].nxt) {
		int v = g[i].to;
		if (v == pr[u])  continue;
		w[v] = g[i].w, c[v] = g[i].c;
		col[c[v]].push_back(v);
		pr[v] = u, dep[v] = dep[u] + 1;
		dfs1(v);
		siz[u] += siz[v];
		siz[hs[u]] < siz[v] && (hs[u] = v);
	}
}

void dfs2(int u = rt, int tp = rt) {
	static int t = 0;
	id[u] = ++t;
	top[u] = tp;
	if (!hs[u])  return;
	dfs2(hs[u], tp);
	for (int i = g.hd[u]; i; i = g[i].nxt) {
		int v = g[i].to;
		if (v == pr[u] || v == hs[u])  continue;
		dfs2(v, v);
	}
}

int inline qry(int u, int v, bianry_index_tree &tr = ::tr) {
	int res = 0;
	for (; top[u] != top[v]; v = pr[top[v]]) {
		if (dep[top[u]] > dep[top[v]])  swap(u, v);
		res += tr.qry(id[top[v]], id[v]);
	}
	if (dep[u] > dep[v])  swap(u, v);
	res += tr.qry(id[u] + 1, id[v]);
	return res;
}

void inline solve(int c) {
	loop (i, col[c].size()) {
		int u = col[c][i];
		sum.upd(id[u], +w[u]);
		cnt.upd(id[u], +1);
	}
	loop (i, qy[c].size()) {
		query &q = qy[c][i];
		int id = q.id, u = q.u, v = q.v, w = q.w, res = qry(u, v);
		res += qry(u, v, cnt) * w - qry(u, v, sum);
		ans[id] = res;
	}
	loop (i, col[c].size()) {
		int u = col[c][i];
		sum.upd(id[u], -w[u]);
		cnt.upd(id[u], -1);
	}
}

int main() {
	read(n), read(m);
	cont (i, n - 1) {
		int u, v, w, c;
		read(u), read(v), read(c), read(w);
		g.link(u, v, w, c);
	}
	dfs1();
	dfs2();
	cont (u, n) {
		tr.upd(id[u], w[u]);
	}
	cont (i, m) {
		int u, v, w, c;
		read(c), read(w), read(u), read(v);
		qy[c].push_back(query(i, u, v, w, c));
	}
	cont (c, n) {
		if (!qy[c].size())  continue;
		solve(c);
	}
	cont (i, m) {
		write(ans[i]);
	}
	flush();
}

Measured memory_bytes: 28688