#include <cstdio>
#include <algorithm>
#include <cmath>
#include <vector>
#include <iostream>
using namespace std;

#define st first
#define nd second

const int N = (int) 1e5 + 5;
const int LOGN = (int) log2(N) + 3;
const int INF = (int) 1e9 + 9;

struct TEdge {
	int v, c, w;
	TEdge() {}
	TEdge(int v, int c, int w) : v(v), c(c), w(w) {}
};

struct TNode {
	int in, ou, c, w;
	TNode() {}
	TNode(int in, int ou, int c, int w) : in(in), ou(ou), c(c), w(w) {}
	bool operator < (const TNode &op) const {
		return in == op.in ? ou < op.ou : in < op.in;
	}
} node[N];

struct TQuery {
	int c, w, u, v;
	TQuery() {}
	TQuery(int c, int w, int u, int v) : c(c), w(w), u(u), v(v) {}
} query[N];

int n, q;
vector <TEdge> g[N];

int vtime;
int in[N], ou[N];
TEdge edgeNode[N];

int logn;
int depth[N], dad[N][LOGN];
long long dist[N];

int pos;
long long cntQuery[N], sumQuery[N];

vector <int> color;
bool markColor[N];
vector <int> colOut[N];

struct TData {
	int u, c, idx, minus;
	TData() {}
	TData(int u, int c, int idx, int minus) : u(u), c(c), idx(idx), minus(minus) {}
	bool operator < (const TData &op) const {
		return in[u] < in[op.u];
	}
};

vector <TData> ver;

void dfsEulerTour(int u, int p) {
	in[u] = ++vtime; 
	for (int i = 0; i < g[u].size(); i++) {
		int v = g[u][i].v, w = g[u][i].w;
		if (v == dad[u][0]) continue;
		edgeNode[v] = g[u][i];
		depth[v] = depth[u] + 1;
		dist[v] = dist[u] + w;
		dfsEulerTour(v, dad[v][0] = u);
	}
	ou[u] = ++vtime;
}

void buildLca() {
	for (int k = 1; k <= logn; k++)
		for (int i = 1; i <= n; i++) dad[i][k] = dad[dad[i][k - 1]][k - 1];
}

int findLca(int u, int v) {
	for (int k = logn; k >= 0; k--)
		if (depth[dad[u][k]] >= depth[v]) u = dad[u][k];
	for (int k = logn; k >= 0; k--)
		if (depth[dad[v][k]] >= depth[u]) v = dad[v][k];
	if (u == v) return u;
	for (int k = logn; k >= 0; k--)
		if (dad[u][k] != dad[v][k]) {
			u = dad[u][k];
			v = dad[v][k];
		}
	return dad[u][0];
}

void compress() {
	vector <int> zip; zip.push_back(0);
	for (int i = 1; i <= n; i++) zip.push_back(ou[i]);
	sort(zip.begin(), zip.end());
	for (int i = 1; i <= n; i++) ou[i] = lower_bound(zip.begin(), zip.end(), ou[i]) - zip.begin(); 
}

void init() {
	logn = log2(n) + 1;
	depth[1] = 1;
	dfsEulerTour(1, 0);
	buildLca();
	compress();
	for (int i = 1; i <= n; i++) node[i] = TNode(in[i], ou[i], edgeNode[i].c, edgeNode[i].w);
	pos = 1;
	sort(node + 1, node + 1 + n);
}

vector <pair <int, long long> > fw[N];

void upd(int c, int i, int w) {
	for (; i < fw[c].size(); i += i & -i) {
		fw[c][i].st++;
		fw[c][i].nd += w;
	}
}

pair <int, long long> get(int c, int i) {
	pair <int, long long> res = make_pair(0, 0LL);
	for (; i > 0; i -= i & -i) {
		res.st += fw[c][i].st;
		res.nd += fw[c][i].nd;
	}
	return res;
}

int main() {
	//freopen("ColorfulTree.inp", "r", stdin);
  //freopen("ColorfulTree.out", "w", stdout);
	scanf("%d %d", &n, &q);
	for (int i = 1; i < n; i++) {
		int u, v, c, w; scanf("%d %d %d %d", &u, &v, &c, &w);
		g[u].push_back(TEdge(v, c, w));
		g[v].push_back(TEdge(u, c, w));
	}
	init();
	for (int i = 1; i <= q; i++) {
		int c, w, u, v; scanf("%d %d %d %d", &c, &w, &u, &v);
		int p = findLca(u, v);
		query[i] = TQuery(c, w, u, v);
		ver.push_back(TData(u, c, i, 1));
		ver.push_back(TData(v, c, i, 1));
		ver.push_back(TData(p, c, i, -1));
		colOut[c].push_back(ou[u]);
		colOut[c].push_back(ou[v]);
		colOut[c].push_back(ou[p]);
		if (markColor[c] == false) {
			color.push_back(c);
			markColor[c] = true;
		}
	}
	for (int i = 1; i <= n; i++) {
		int c = edgeNode[i].c;
		colOut[c].push_back(ou[i]);
		if (markColor[c] == false) {
			color.push_back(c);
			markColor[c] = true;
		}
	}
	for (int iCol = 0; iCol < color.size(); iCol++) {
		int c = color[iCol];
		// colOut[c].push_back(INF);
		sort(colOut[c].begin(), colOut[c].end());
		colOut[c].resize(distance(colOut[c].begin(), unique(colOut[c].begin(), colOut[c].end())));
		fw[c].resize(colOut[c].size() + 2);
	}
	/*cerr << "------------------\n";
	for (int i = 1; i <= n; i++) cerr << node[i].in << " " << node[i].ou << " " << node[i].c << " " << node[i].w << endl;
	cerr << "------------------\n";*/
	sort(ver.begin(), ver.end());
	for (int i = 0; i < ver.size(); i++) {
		int u = ver[i].u, c = ver[i].c, idx = ver[i].idx, minus = ver[i].minus;
		//cerr << u << " " << c << " " << idx << " " << minus << endl;
		while (pos <= n && node[pos].in <= in[u]) {
			int position = lower_bound(colOut[node[pos].c].begin(), colOut[node[pos].c].end(), node[pos].ou) - colOut[node[pos].c].begin() + 1;
			if (position < colOut[node[pos].c].size() + 1) {
				upd(node[pos].c, position, node[pos].w);
				// if (pos == 3) cerr << node[pos].c << " " << position << " " << node[pos].w << endl;
			}
 			pos++;
		} 
		if (colOut[c].size() == 0) continue;
		pair <int, long long> resRight = get(c, fw[c].size() - 1);
		int position = upper_bound(colOut[c].begin(), colOut[c].end(), ou[u]) - colOut[c].begin();
		pair <int, long long> resLeft = make_pair(0, 0);
		resLeft = get(c, position);
		long long temp1 = 0, temp2 = 0;
		if (minus > 0) {
			temp1 += (resRight.st - resLeft.st);
			temp2 += (resRight.nd - resLeft.nd);
		} else {
			temp1 -= 2LL * (resRight.st - resLeft.st);
			temp2 -= 2LL * (resRight.nd - resLeft.nd);
		}
		/*cntQuery[idx] += 1LL * minus * (resRight.st - resLeft.st);
		sumQuery[idx] += 1LL * minus * (resRight.nd - resLeft.nd);*/
		
		if (edgeNode[u].c == c) {
			// cntQuery[idx] += minus;
			// sumQuery[idx] += 1LL * minus * edgeNode[u].w;
			
			if (minus > 0) {
				temp1 += minus;
				temp2 += 1LL * edgeNode[u].w;
			} else {
				temp1 -= 2LL;
				temp2 -= 2LL * edgeNode[u].w;
			}
		}
		cntQuery[idx] += temp1;
		sumQuery[idx] += temp2;
		if (u == 8 || u == 5 || u == 9) {
			//cerr << "~: " << u << " " << temp1 << " " << temp2 << endl;
		}
	}
	// cerr << "fw: " << get(1, fw[1].size() - 1).first << " " << get(1, fw[1].size() - 1).second << endl;
	for (int i = 1; i <= q; i++) {
		int u = query[i].u, v = query[i].v, p = findLca(u, v), w = query[i].w;
		long long ans = dist[u] + dist[v] - 2LL * dist[p];
		//cerr << "#Q: " << sumQuery[i] << " " << cntQuery[i] << endl;
		ans -= sumQuery[i];
		ans += cntQuery[i] * w;
		printf("%lld\n", ans);
	}
	return 0;
}

/*
5 3
1 2 1 10
1 3 2 20
2 4 4 30
5 2 1 40
1 100 1 4
1 100 1 5
3 1000 3 4

10 5
6 1 1 20
3 2 3 22
9 3 2 10
10 4 4 6
9 5 5 25
9 6 3 22
1 7 2 25
4 8 1 19
9 10 5 14
1 100 1 4
2 70 1 9
3 60 4 6
4 50 3 7
1 40 5 8

6 1
1 2 1 13
4 3 2 8
1 4 1 17
1 5 3 15
1 6 1 8
1 20 3 6
*/


Measured memory_bytes: 48612