#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<sstream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<climits>
#include<cmath>
#include<string>
#include<vector>
#include<set>
#include<map>
#include<queue>
#include<numeric>
#include<functional>
#include<algorithm>
#include<bitset>
#include<tuple>
#include<unordered_set>
#include<unordered_map>
#include<random>
#include<array>
#include<cassert>
using namespace std;
#define INF (1<<29)
#define rep(i,n) for(int i=0;i<(int)(n);i++)
#define all(v) v.begin(),v.end()
#define uniq(v) v.erase(unique(all(v)),v.end())


int n, q;
vector<tuple<int, int, int>> edge[100000];


vector<long long> euler_tour;
int eindex[100000];


pair<int, long long> cs[100001];
map<int, pair<int, long long>> ccs[100001];


int _par[100001];



class LCA {
	int lg, n;
	std::vector<int> _depth, par;
	int dfs(const int parent[], int u) {
		if (parent[u] == -1)return _depth[u] = 1;
		if (_depth[u] != 0)return _depth[u];
		return _depth[u] = dfs(parent, parent[u]) + 1;
	}
public:
	LCA(const int parent[], int n) :n(n), _depth(n, 0) {
		lg = 1;
		while ((1 << lg) < n)lg++;
		lg++;
		for (int i = 0; i < n; i++)dfs(parent, i);
		par.resize(n * lg);
		for (int i = 0; i < n; i++)par[i] = parent[i];
		for (int i = 1; i < lg; i++)
			for (int v = 0; v < n; v++)
				if (par[(i - 1) * n + v] != -1)par[i * n + v] = par[(i - 1) * n + par[(i - 1) * n + v]];
				else par[i * n + v] = -1;
	}
	int query(int u, int v)const {
		if (_depth[u] > _depth[v])std::swap(u, v);
		for (int i = lg - 1; i >= 0; i--)
			if (_depth[u] <= _depth[v] - (1 << i))
				v = par[i * n + v];
		if (u == v)return u;
		for (int i = lg - 1; i >= 0; i--) {
			if (par[i * n + u] != par[i * n + v]) {
				u = par[i * n + u];
				v = par[i * n + v];
			}
		}
		return par[u];
	}
	int depth(int u)const {//rootの深さが1
		return _depth[u];
	}
};








void dfs(int u, int par, int ec, int ew) {
	_par[u] = par;

	cs[ec].first++;
	cs[ec].second += ew;
	ccs[ec][euler_tour.size()] = cs[ec];
	eindex[u] = euler_tour.size();

	euler_tour.push_back(ew);
	
	for (const auto &t : edge[u]) {
		int b, c, d;
		tie(b, c, d) = t;
		if (b == par)continue;

		dfs(b, u, c, d);
	}
	cs[ec].first--;
	cs[ec].second -= ew;
	ccs[ec][euler_tour.size()] = cs[ec];
	euler_tour.push_back(-ew);
}

void init() {
	dfs(0, -1, n, 0);

	long long s = 0;
	rep(i, euler_tour.size()) {
		s += euler_tour[i];
		euler_tour[i] = s;
	}
}




pair<int, long long> qu(int c,int idx){
	auto it = ccs[c].upper_bound(idx);
	if (it != ccs[c].begin()) {
		--it;
		return it->second;
	}
	return make_pair(0, 0);
}

int main() {
	ios::sync_with_stdio(0);
	cin.tie(0);

	cin >> n >> q;
	rep(i, n - 1) {
		int a, b, c, d;
		cin >> a >> b >> c >> d;
		a--; b--; c--;
		edge[a].emplace_back(b, c, d);
		edge[b].emplace_back(a, c, d);
	}

	init();

	LCA lca(_par, n);

	rep(i,q) {
		int x, y, u, v;
		cin >> x >> y >> u >> v;
		x--; u--; v--;
		int r = lca.query(u, v);

		if (u == r || v == r) {
			int ui, vi;
			ui = eindex[u];
			vi = eindex[v];
			if (ui > vi) {
				swap(ui, vi);
			}
			long long ans = euler_tour[vi];
			ans -= euler_tour[ui];
			int cnt = 0;
			{
				auto p = qu(x, ui);
				cnt -= p.first;
				ans += p.second;
			}
			{
				auto p = qu(x, vi);
				cnt += p.first;
				ans -= p.second;
			}
			ans += (long long)cnt * y;
			cout << ans << endl;
		}
		else {
			int ui, vi;
			ui = eindex[u];
			vi = eindex[v];
			int ri = eindex[lca.query(u, v)];


			long long ans = euler_tour[ui];
			ans += euler_tour[vi];
			ans -= euler_tour[ri] * 2;
			int cnt = 0;
			{
				auto p = qu(x, ui);
				cnt += p.first;
				ans -= p.second;
			}
			{
				auto p = qu(x, vi);
				cnt += p.first;
				ans -= p.second;
			}
			{
				auto p = qu(x, ri);
				cnt -= p.first * 2;
				ans += p.second * 2;
			}
			ans += (long long)cnt * y;
			cout << ans << endl;
		}

	}



	return 0;
}

Measured memory_bytes: 44912