#include <bits/stdc++.h>
using namespace std;

vector<int> depth;
vector<vector<int>> parent;
queue<int> qu;
vector<int> vtoi;
class edge{
public:
	int cost, from, to, col;
	edge(int c, int f, int t, int co){
		cost = c;
		from = f;
		to = t;
		col = co;
	}
};
using edges = vector<edge>;
using graph = vector<edges>;
class etedge{
public:
	int idx, cost, col, num;
	etedge(int i, int c, int co, int n){
		idx = i;
		cost = c;
		col = co;
		num = n;
	}
};
vector<etedge> et;
vector<vector<etedge>> etcol;
int lca(int u, int v){
	if(depth[u] > depth[v]) swap(u, v);
	int d = depth[v] - depth[u];
	for(int i=0; i<20; ++i)
		if((d >> i) & 1)
			v = parent[v][i];
	for(int i=19; i>=0; --i){
		if(parent[v][i] != parent[u][i]){
			v = parent[v][i];
			u = parent[u][i];
		}
	}
	if(u != v && parent[u][0] == parent[v][0])
		u = v = parent[v][0];
	return v;
}
void dfs(int v, graph &g, vector<int> &vtoi, vector<etedge> &et){
	for(auto e:g[v]){
		if(vtoi[e.to] == -1){
			vtoi[e.to] = et.size();
			et.push_back(etedge(et.size(), e.cost, e.col, 1));
			dfs(e.to, g, vtoi, et);
			et.push_back(etedge(et.size(), -e.cost, e.col, -1));
		}
	}
}
long long dist(int v, int col, int cost, vector<vector<etedge>> &etcol, vector<etedge> &et, vector<int> &vtoi){
	if(v == 0) return 0;
	int idx = vtoi[v];
	long long ret = et[idx].cost;
	int l = 0; int r = etcol[col].size();
	while(l+1 < r){
		int m = (l+r)/2;
		if(etcol[col][m].idx <= idx) l = m;
		else r = m;
	}
//	cout << "default " << ret << "\n";
	if(etcol[col].size() > 0 && etcol[col][l].idx <= idx){
		ret -= etcol[col][l].cost;
//		cout << "minus " << etcol[col][l].cost << "\n";
		ret += (long long)etcol[col][l].num * cost;
//		cout << "plus " << etcol[col][l].num << " * " << cost << "\n";
	}
//	cout << v+1 << " " << col << " " << cost << " " << ret << "\n";
	return ret;
}

int main(){
	cin.tie(0);
	ios::sync_with_stdio(false);
	int n, q; cin >> n >> q;
	graph g(n);
	for(int i=0; i<n-1; ++i){
		int a, b, c, d; cin >> a >> b >> c >> d;
		--a; --b; --c;
		g[a].push_back(edge(d, a, b, c));
		g[b].push_back(edge(d, b, a, c));
	}
	depth.resize(n, -1);
	parent.resize(n, vector<int>(20));
	qu.push(0);
	depth[0] = 0;
	parent[0][0] = 0;
	while(!qu.empty()){
		int p = qu.front(); qu.pop();
		for(auto e:g[p]){
			int t = e.to;
			if(t != parent[p][0]){
				qu.push(t);
				depth[t] = depth[p] + 1;
				parent[t][0] = p;
			}
		}
	}
	for(int i=1; i<20; ++i)
		for(int j=0; j<n; ++j)
			parent[j][i] = parent[parent[j][i-1]][i-1];
	vtoi.resize(n, -1);
	vtoi[0] = 0;
	dfs(0, g, vtoi, et);
	etcol.resize(n-1);
	for(auto i:et)
		etcol[i.col].push_back(i);
	for(auto &i:etcol)
		for(size_t j=1; j<i.size(); ++j){
			i[j].cost += i[j-1].cost;
			i[j].num += i[j-1].num;
		}
	for(size_t i=1; i<et.size(); ++i){
		et[i].cost += et[i-1].cost;
		et[i].num += et[i-1].num;
	}
	for(int i=0; i<q; ++i){
		int x, y, u, v; cin >> x >> y >> u >> v;
		--x; --u; --v;
		cout << dist(u, x, y, etcol, et, vtoi) + dist(v, x, y, etcol, et, vtoi) - 2 * dist(lca(u, v), x, y, etcol, et, vtoi) << "\n";
	}
//	for(size_t i=0; i<et.size(); ++i)
//		cout << i << " " << et[i].cost << "\n";
//	for(Int i=0; i<n; ++i)
//		cout << i+1 << " " << vtoi[i] << "\n";
//	for(size_t i=0; i<etcol[0].size(); ++i)
//		cout << i << " " << etcol[0][i].idx << " " << etcol[0][i].cost << "\n";
}

Measured memory_bytes: 38512