#ifdef DEBUG
	#define _GLIBCXX_DEBUG
#endif
#include <algorithm>
#include <bitset>
#include <cassert>
#include <chrono>
#include <climits>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <deque>
#include <fstream>
#include <functional>
#include <iostream>
#include <iomanip>
#include <map>
#include <numeric>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <sstream>
#include <tuple>
#include <vector>

using namespace std;
using namespace chrono;

#ifdef DEBUG
	#define LOCAL_INPUT_FILE
#else
	//#define USE_FILE_IO
#endif

#ifdef USE_FILE_IO
	#define INPUT_FILE "input.txt"
	#define OUTPUT_FILE "output.txt"
	#define cin ____cin
	#define cout ____cout
	ifstream cin(INPUT_FILE);
	ofstream cout(OUTPUT_FILE);
#else
	#ifdef LOCAL_INPUT_FILE
		#define cin ____cin
		ifstream cin("input.txt");
	#endif
#endif

const int infinity = (int)1e9 + 42;
const int64_t llInfinity = (int64_t)1e18 + 256;
const int module = (int)1e9 + 7; 
const long double eps = 1e-8;

mt19937_64 randGen(system_clock().now().time_since_epoch().count());

inline void raiseError(string errorCode) {
	cerr << "Error : " << errorCode << endl;
	exit(42);
}

struct Edge {
	int a, b, c, d;
};

signed main() {
	#ifndef USE_FILE_IO
		ios_base::sync_with_stdio(false);
	#endif
	int n, q; cin >> n >> q;
	vector< vector<Edge> > g(n);
	for (int i = 1; i < n; ++i) {
		int a, b, c, d; cin >> a >> b >> c >> d; --a; --b; --c;
		g[a].push_back({a, b, c, d});
		g[b].push_back({b, a, c, d}); 
	}
	
	const int lay = 20;
	vector< vector<int> > up(n, vector<int>(lay));
	vector<int> l(n), r(n);
	vector<int> tin(n), tout(n);
	vector<int> ver;
	vector<int64_t> sum;
	vector< vector<int> > col(n);
	vector< vector<int64_t> > csum(n);
	vector< vector<int> > ccnt(n);
	sum.push_back(0);
	for (int i = 0; i < n; ++i) {
		csum[i].push_back(0);
		ccnt[i].push_back(0);
	}
	int timer = 0;
	
	function<void(int, int)> dfs = [&](int v, int p) {
		tin[v] = timer++;
		up[v][0] = p;
		for (int i = 1; i < lay; i++) {
			up[v][i] = up[up[v][i-1]][i-1];
		}
		for (Edge e : g[v]) {
			int to = e.b;
			if (to == p) {
				continue;
			}
			
			l[to] = r[to] = int(ver.size());
			col[e.c].push_back(ver.size());
			ver.push_back(to);
			sum.push_back(sum.back() - e.d);
			csum[e.c].push_back(csum[e.c].back() - e.d);
			ccnt[e.c].push_back(ccnt[e.c].back() - 1);
			
			dfs(to, v);
			
			r[v] = int(ver.size());
			col[e.c].push_back(ver.size());
			ver.push_back(v);
			sum.push_back(sum.back() + e.d);
			csum[e.c].push_back(csum[e.c].back() + e.d);
			ccnt[e.c].push_back(ccnt[e.c].back() + 1);
		}
		tout[v] = timer++;
	};
	
	l[0] = -1;
	dfs(0, 0);
	
	auto upper = [&](int a, int b) {
		return tin[a] <= tin[b] && tout[a] >= tout[b];
	};
	
	auto lca = [&](int a, int b) {
		if (upper(a, b)) {
			return a;
		}
		if (upper(b, a)) {
			return b;
		}
		for (int i = lay-1; i >= 0; i--) {
			if (!upper(up[a][i], b)) {
				a = up[a][i];
			}
		}
		return up[a][0];
	};
	
	//~ for (int i : sum) {
		//~ cout << i << " ";
	//~ }
	//~ cout << endl;
	//~ for (int i : ver) {
		//~ cout << i << " ";
	//~ }
	//~ cout << endl;
	//~ for (int i = 0; i < n; ++i) {
		//~ cout << l[i] << " " << r[i] << endl;
	//~ }
	//~ cout << "---" << endl;
	
	auto path = [&](int u, int v, int x, int y) -> int64_t {
		assert(upper(v, u));
		if (u == v) {
			return 0;
		}
		int pl = l[u]+1, pr = r[v]+1;
		assert(pl < pr);
		int64_t soom = sum[pr] - sum[pl];
		//~ cout << "soom = " << soom <<  " " << u+1 << " " << v+1 << " :: " << pl << " " << pr << endl;
		int cl = lower_bound(begin(col[x]), end(col[x]), pl) - begin(col[x]);
		int cr = lower_bound(begin(col[x]), end(col[x]), pr) - begin(col[x]);
		soom -= csum[x][cr] - csum[x][cl];
		soom += int64_t(y) * (ccnt[x][cr] - ccnt[x][cl]);
		return soom;
	};
	
	for (int i = 0; i < q; ++i) {
		int x, y, u, v; cin >> x >> y >> u >> v; --u; --v; --x;
		int l = lca(u, v);
		cout << path(u, l, x, y) + path(v, l, x, y) << "\n";
	}
	
	return 0;
}


Measured memory_bytes: 48612