#include <bits/stdc++.h>
using namespace std::literals::string_literals;
using i64 = long long;
using std::cout;
using std::endl;
using std::cin;

template<typename T>
std::vector<T> make_v(size_t a){return std::vector<T>(a);}

template<typename T,typename... Ts>
auto make_v(size_t a,Ts... ts){
  return std::vector<decltype(make_v<T>(ts...))>(a,make_v<T>(ts...));
}

struct SegmentTree {
	std::vector<int> seg;
	int sz = 1;
	
	SegmentTree(int n) {
		while(sz < n) sz <<= 1;
		seg.assign(sz << 1, 0);
	}
	void change(int k, int x) {
		k += sz;
		seg[k] = x;
		
		while(k >>= 1) seg[k] = seg[k << 1 ^ 0] + seg[k << 1 ^ 1];
	}
	int query(int a, int b) {
		int L = 0, R = 0;
		for(a += sz, b += sz; a < b; a >>= 1, b >>= 1) {
			if(a & 1) L = L + seg[a++];
			if(b & 1) R = seg[--b] + R;
		}
		return L + R;
	}
	int operator[](int k) {
		return seg[k + sz];
	}
};

using namespace std;
struct LowestCommonAncestor{
	vector<vector<int>> g, parent;
	vector<int> depth;
	bool built = false;
	int N;
	
	const int logN = 20;
	
	LowestCommonAncestor(int n) : N(n) {
		g.resize(N);
		parent.resize(logN, vector<int>(N));
		depth.resize(N);
	}
	
	void add_edge(int u, int v){
		g[u].push_back(v);
		g[v].push_back(u);
	}
	
	void dfs(int v, int par = -1, int d = 0){
		parent[0][v] = par;
		depth[v] = d;
		
		for(auto e:g[v]){
			if(e == par) continue;
			dfs(e, v, d + 1);
		}
	}
	
	void build(){
		dfs(0);
		for(int k = 0; k < logN - 1; k++){
			for(int i = 0; i < N; i++){
				if(parent[k][i] < 0) parent[k + 1][i] = -1;
				else parent[k + 1][i] = parent[k][parent[k][i]];
			}
		}
	}
	
	int get(int u, int v){
		if(!built) build(); built = true;
		if(depth[u] > depth[v]) swap(u, v);
		
		for(int k = 0; k < logN; k++){
			if(((depth[v] - depth[u]) >> k) & 1){
				v = parent[k][v];
			}
		}
		if(u == v) return u;
		
		for(int k = logN - 1; k >= 0; k--){
			if(parent[k][u] == parent[k][v]) continue;
			u = parent[k][u];
			v = parent[k][v];			
		}
		
		return parent[0][u];
	}
};

int main() {
	int n, q; scanf("%d%d", &n, &q);
	int m = n - 1;
	LowestCommonAncestor lca(n);
	std::vector<std::vector<std::pair<int, int>>> g(n);
	std::vector<std::vector<int>> edges(n);
	std::vector<int> a(m), b(m), c(m), d(m);
	for(int i = 0; i < m; i++) {
		scanf("%d%d%d%d", &a[i], &b[i], &c[i], &d[i]); a[i]--; b[i]--;
		
		lca.add_edge(a[i], b[i]);
		edges[c[i]].push_back(i);
		g[a[i]].push_back({b[i], i});
		g[b[i]].push_back({a[i], i});
	}
	
	std::vector<std::vector<int>> vec(n);
	std::vector<int> x(q), y(q), u(q), v(q);
	for(int i = 0; i < q; i++) {
		scanf("%d%d%d%d", &x[i], &y[i], &u[i], &v[i]);
		u[i]--; v[i]--;
		
		vec[x[i]].push_back(i);
	}
	
	std::vector<int> S(m), T(m), tour;
	std::vector<int> fastEdge(n, -1), parEdge(n, -1);
	std::function<void (int, int)> dfs = [&](int v, int par) {
		for(auto e: g[v]) {
			if(e.first == par) continue;
			if(fastEdge[v] == -1) fastEdge[v] = e.second;
			S[e.second] = tour.size();
			tour.push_back(e.second);
			
			parEdge[e.first] = e.second;
			dfs(e.first, v);
			
			T[e.second] = tour.size();
			tour.push_back(e.second);
		}
	};
	dfs(0, -1);
	assert(tour.size() == 2 * (n - 1));

	SegmentTree seg(tour.size()), kiri(tour.size());
	for(int i = 0; i < m; i++) {
		seg.change(S[i], d[i]);
		seg.change(T[i], -d[i]);
	}
	
	std::vector<int> ans(q, -1);
	for(int color = 1; color < n; color++) {
		for(auto i: edges[color]) {
			seg.change(S[i], 0);
			seg.change(T[i], 0);
			kiri.change(S[i], 1);
			kiri.change(T[i], -1);
		}
		
		for(auto i: vec[color]) {
			int z = lca.get(u[i], v[i]);
			int yEdge = 0, cost = 0;
			if(z == u[i]) {
				yEdge = kiri.query(S[fastEdge[u[i]]], S[parEdge[v[i]]] + 1);
				cost  = seg.query(S[fastEdge[u[i]]], S[parEdge[v[i]]] + 1);
			} else if(z == v[i]) {
				yEdge = kiri.query(S[fastEdge[v[i]]], S[parEdge[u[i]]] + 1);
				cost  = seg.query(S[fastEdge[v[i]]], S[parEdge[u[i]]] + 1);
			} else {
				yEdge = kiri.query(S[fastEdge[z]], S[parEdge[u[i]]] + 1) + kiri.query(S[fastEdge[z]], S[parEdge[v[i]]] + 1);
				cost  = seg.query(S[fastEdge[z]], S[parEdge[u[i]]] + 1) + seg.query(S[fastEdge[z]], S[parEdge[v[i]]] + 1);
			}
			
			ans[i] = cost + yEdge * y[i];
		}
		
		for(auto i: edges[color]) {
			seg.change(S[i], d[i]);
			seg.change(T[i], -d[i]);
			kiri.change(S[i], 0);
			kiri.change(T[i], 0);
		}
	}
	for(auto v: ans) printf("%d\n", v);
	return 0;
}


Measured memory_bytes: 44404