#include <iostream>
#include <iomanip>
#include <random>
#include <algorithm>
#include <vector>
#include <set>
#include <map>
#include <cmath>
#include <numeric>
#include <cstdlib>
#include <cstring>
#include <deque>
#include <sstream>
#include <bitset>
#include <cassert>
#include <fstream>
#include <queue>

#define len(X) ((int)(X).size())

#ifdef __LOCAL
	#define DBG(X) cout << #X << "=" << (X) << endl;
#else
	#define DBG(X)
	#define endl '\n'
#endif
 
using namespace std;

using ll = long long int;
using ull = unsigned long long int;
using ld  = long double;
using pii = pair<int, int>;
using pll = pair<ll, ll>;

const int INT_INF = (int)(2e9);
const ll  LL_INF  = (ll)(2e18);

const int NIL = -1;
static mt19937 _g(time(nullptr));

inline ll randint(ll a, ll b) { ll w = (_g() << 31LL) ^ _g(); return a + w % (b - a + 1); }
inline void fast_io() { ios_base::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr); };
template<typename T> inline T sign(T x) { return T(x > 0) - T(x < 0); }
template<typename T, typename S> inline ostream& operator<<(ostream& os, const pair<T, S> p) { cout << "[" << p.first << ";" << p.second << "]"; return os; }
template<typename T> inline ostream& operator<<(ostream& os, const vector<T>& v) { for(auto el: v) cout << el << " "; return os; }
template<typename T> inline T fetch() { T ret; cin >> ret; return ret; }
template<typename T> inline void goodbye(const T& val) { cout << val << endl; exit(0); }

const int MAXN = (int)1e5 + 777;
const int MAX_LOGN = 20;

vector<pair<int, pll>> tree[MAXN];
int parent[MAX_LOGN][MAXN], depth[MAXN];
ll w_depth[MAXN];
int n, q;

vector<int> quests[MAXN];
map<pii, int> cnt;
map<pii, ll> sum;

void prepare(int v, int p) {
	parent[0][v] = p;

	for(auto& ed: tree[v]) {
		int u = ed.first;

		if(u != p) {
			depth[u] = depth[v] + 1;
			w_depth[u] = w_depth[v] + ed.second.second;

			prepare(u, v);
		}
	}
}

int LCA(int v, int u) {
	if(depth[v] < depth[u]) {
		swap(v, u);
	}

	int d = depth[v] - depth[u];

	for(int log = 0; log < MAX_LOGN; ++log) {
		if((d >> log) & 1) {
			v = parent[log][v];
		}
	}

	if(v == u) {
		return v;
	} else {
		for(int log = MAX_LOGN - 1; log >= 0; --log) {
			int v2 = parent[log][v];
			int u2 = parent[log][u];

			if(v2 != u2) {
				v = v2;
				u = u2;
			}
		}

		return parent[0][v];
	}
}

int cur_cnt[MAXN];
ll cur_sum[MAXN];

void find(int v, int p) {
	for(auto& color: quests[v]) {
		cnt[make_pair(v, color)] = cur_cnt[color];
		sum[make_pair(v, color)] = cur_sum[color];
	}

	for(auto& ed: tree[v]) {
		int u = ed.first;

		if(u != p) {
			++cur_cnt[ed.second.first];
			cur_sum[ed.second.first] += ed.second.second;

			find(u, v);

			cur_sum[ed.second.first] -= ed.second.second;
			--cur_cnt[ed.second.first];
		}
	}
}

void solve() {
	cin >> n >> q;

	for(int i = 0; i < n - 1; ++i) {
		int v, u;
		ll c, d;
		cin >> v >> u >> c >> d;
		--v, --u;

		tree[v].emplace_back(u, make_pair(c, d));
		tree[u].emplace_back(v, make_pair(c, d));
	}

	const int root = 0;
	prepare(root, root);

	for(int log = 1; log < MAX_LOGN; ++log) {
		for(int v = 0; v < n; ++v) {
			parent[log][v] = parent[log - 1][parent[log - 1][v]];
		}
	}

	vector<pair<pii, pll>> queries;

	for(int i = 0; i < q; ++i) {
		ll x, y;
		int v, u;
		cin >> x >> y >> v >> u;
		--v, --u;

		int w = LCA(v, u);
		queries.emplace_back(make_pair(v, u), make_pair(x, y));

		quests[v].push_back(x);
		quests[u].push_back(x);
		quests[w].push_back(x);
	}

	find(root, root);

	for(auto& que: queries) {
		int v = que.first.first, u = que.first.second;
		ll x = que.second.first, y = que.second.second;

		int w = LCA(v, u);
		ll answ = w_depth[v] + w_depth[u] - 2 * w_depth[w];
		answ -= sum[make_pair(v, x)] + sum[make_pair(u, x)] - 2 * sum[make_pair(w, x)];
		answ += y * (cnt[make_pair(v, x)] + cnt[make_pair(u, x)] - 2 * cnt[make_pair(w, x)]);

		cout << answ << '\n';
	}
}

int main() {
	fast_io();
	solve();

	return 0;
}


Measured memory_bytes: 60592