#include<iostream>
#include<string>
#include<cstdio>
#include<vector>
#include<cmath>
#include<algorithm>
#include<functional>
#include<iomanip>
#include<queue>
#include<ciso646>
#include<random>
#include<map>
#include<set>
#include<bitset>
#include<stack>
#include<unordered_map>
#include<utility>
#include<cassert>
using namespace std;

typedef long long ll;

typedef unsigned long long ul;
typedef unsigned int ui;
const ll mod = 1000000007;
const ll INF = mod * mod;
typedef pair<int, int> P;
#define stop char nyaa;cin>>nyaa;
#define rep(i,n) for(int i=0;i<n;i++)
#define per(i,n) for(int i=n-1;i>=0;i--)
#define Rep(i,sta,n) for(int i=sta;i<n;i++)
#define rep1(i,n) for(int i=1;i<=n;i++)
#define per1(i,n) for(int i=n;i>=1;i--)
#define Rep1(i,sta,n) for(int i=sta;i<=n;i++)
typedef pair<ll, ll> LP;
typedef vector<int> vec;
typedef vector<string> svec;
typedef long double ld;
typedef pair<ld, ld> LDP;
const ld eps = 1e-8;

vector<int> gG[100000];
int root;
int parent[17][100000];
int depth[100000];
void dfs2(int v, int p, int d) {
	parent[0][v] = p;
	depth[v] = d;
	for (int i = 0; i < (int)gG[v].size(); i++) {
		if (gG[v][i] != p)dfs2(gG[v][i], v, d + 1);
	}
}
void init(int V) {
	dfs2(root, -1, 0);
	for (int k = 0; k + 1 < 17; k++) {
		for (int v = 0; v < V; v++) {
			if (parent[k][v] < 0)parent[k + 1][v] = -1;
			else parent[k + 1][v] = parent[k][parent[k][v]];
		}
	}
}
int lca(int u, int v) {
	if (depth[u] > depth[v])swap(u, v);
	for (int k = 0; k < 17; k++) {
		if ((depth[v] - depth[u]) >> k & 1) {
			v = parent[k][v];
		}
	}
	if (u == v)return u;
	for (int k = 16; k >= 0; k--) {
		if (parent[k][u] != parent[k][v]) {
			u = parent[k][u];
			v = parent[k][v];
		}
	}
	return parent[0][u];
}

struct SegT {
private:
	int n; vector<int> node, lazy;
	const int init_c = 0;
public:
	SegT(int sz) {
		n = 1;
		while (n < sz)n <<= 1;
		node.resize(2 * n - 1, init_c);
		lazy.resize(2 * n - 1, 0);
	}
	SegT(vector<int> v) {
		int sz = v.size();
		n = 1;
		while (n < sz)n <<= 1;
		node.resize(2 * n - 1, init_c);
		lazy.resize(2 * n - 1, 0);
		rep(i, sz) {
			node[i + n - 1] = v[i];
		}
		per(i, n - 1) {
			node[i] = f(node[2 * i + 1], node[2 * i + 2]);
		}
	}
	int f(int a, int b) {
		return a + b;
	}
	void eval(int k, int l, int r) {
		node[k] += lazy[k];
		if (r - l > 1) {
			lazy[2 * k + 1] += lazy[k];
			lazy[2 * k + 2] += lazy[k];
		}
		lazy[k] = 0;
	}
	void add(ll x, int a, int b, int k = 0, int l = 0, int r = -1) {
		if (r < 0)r = n;
		eval(k, l, r);
		if (r <= a || b <= l)return;
		if (a <= l && r <= b) {
			lazy[k] += x; eval(k, l, r);
		}
		else {
			add(x, a, b, k * 2 + 1, l, (l + r) / 2);
			add(x, a, b, k * 2 + 2, (l + r) / 2, r);
			node[k] = f(node[k * 2 + 1], node[k * 2 + 2]);
		}
	}
	int query(int a, int b, int k = 0, int l = 0, int r = -1) {
		if (r < 0)r = n;
		eval(k, l, r);
		if (r <= a || b <= l)return init_c;
		if (a <= l && r <= b)return node[k];
		else {
			int vl = query(a, b, k * 2 + 1, l, (l + r) / 2);
			int vr = query(a, b, k * 2 + 2, (l + r) / 2, r);
			return f(vl, vr);
		}
	}
};

int n, q;
struct edge {
	int to, cost; int col;
};
vector<edge> G[1 << 17];

int trans[1 << 17];
int ri[1 << 17];
int dist[1 << 17];

int cur = 0;

struct oper {
	int le, ri, cost;
};
vector<oper> query[1 << 17];
void dfs(int id, int fr) {
	trans[id] = cur; cur++;
	rep(j, G[id].size()) {
		int to = G[id][j].to;
		if (to == fr)continue;
		dist[cur] = dist[trans[id]] + G[id][j].cost;
		dfs(to,id);
		gG[trans[id]].push_back(trans[to]);
		gG[trans[to]].push_back(trans[id]);
		query[G[id][j].col].push_back({ trans[to],ri[trans[to]],G[id][j].cost });
	}
	ri[trans[id]] = cur;
}

struct qquery {
	int cost; int u, v; int qid;
};

void solve() {
	cin >> n >> q;
	rep(i, n-1) {
		int a, b, c, d; cin >> a >> b >> c >> d;
		a--; b--;
		G[a].push_back({ b,d,c });
		G[b].push_back({ a,d,c });
	}
	dfs(0, -1); init(n);
	vector<int> ans(q);
	vector<qquery> que[1<<17];
	rep(i, q) {
		int x, y, u, v; cin >> x >> y >> u >> v;
		u--; v--;
		que[x].push_back({ y,u,v,i });
	}
	SegT st(n);
	vector<int> dd;
	rep(i, n)dd.push_back(dist[i]);
	SegT sd(dd);
	rep1(i, n - 1) {
		rep(j, query[i].size()) {
			oper &q = query[i][j];
			st.add(1,q.le, q.ri);
			sd.add(-q.cost, q.le, q.ri);
		}
		rep(j, que[i].size()) {
			qquery q = que[i][j];
			q.u = trans[q.u];
			q.v = trans[q.v];
			int udist = st.query(q.u, q.u + 1)*q.cost + sd.query(q.u, q.u + 1);
			int vdist = st.query(q.v, q.v + 1)*q.cost + sd.query(q.v, q.v + 1);
			int p = lca(q.u, q.v);
			int pdist = st.query(p, p + 1)*q.cost + sd.query(p, p + 1);
			//cout << q.qid<<" "<<udist << " " << vdist << " " << pdist << endl;
			ans[q.qid] = udist + vdist - 2*pdist;
		}

		rep(j, query[i].size()) {
			oper &q = query[i][j];
			st.add(-1, q.le, q.ri);
			sd.add(q.cost, q.le, q.ri);
		}

	}
	rep(i, q) {
		cout << ans[i] << endl;
	}
}

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

	//cout << fixed << setprecision(10);
	//init();
	solve();
	//stop
		return 0;
}

Measured memory_bytes: 44596