//by Himanshu Shukla
#pragma GCC optimize("O2")
#include <bits/stdc++.h>
using namespace std;
#define FASTIO ios_base::sync_with_stdio(false), cin.tie(0), cout.tie(0)
#define ll long long
#define v32 vector<int>
#define v64 vector<ll>
#define s32 set<int>
#define s64 set<ll>
#define graph vector<s32>
#define p32 pair<int,int>
#define p64 pair<ll,ll>
#define fi first
#define se second
#define ln '\n'
#define debug(x) cout << (#x) << ": " << (x) << ln
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
inline ll add(ll a, ll b, ll m) { return (((a % m + b % m) % m + m) % m); }
inline ll mul(ll a, ll b, ll m) { return (((a % m * b % m) % m + m) % m); }
const double EPS = 1e-6;
const ll MOD = 1e9 + 7;
template <typename T, typename U>
ostream& operator<<(ostream& out, const pair<T,U>& p){
	out << '[' << p.fi << ", " << p.se << ']';
	return out;
}
template <template <typename, typename...> class ContainerType, typename ValueType, typename ...Args>
void print_container(const ContainerType<ValueType, Args...>& c){
	cout << "{ ";
	for(const auto& v : c)
		cout << v << ' ';
	cout << '}' << ln;
}

const int N = 1e5 + 5;
map<p32,p32> weight;
v32 color[N];
v32 sum[N];

struct lca
{
	v32 wdist,ndist;
	vector<v32> up;
	int lgn;
	void dfs(int ii,int pp,graph &g)
	{
		for(auto jj : g[ii])
			if(jj != pp)
			{
				wdist[jj] = weight[{ii,jj}].se + wdist[ii];
				ndist[jj] = 1 + ndist[ii];
				up[jj][0] = ii;
				dfs(jj,ii,g);
			}
	}
	lca(int n,graph &g)
	{
		lgn = ceil(1.0 * log2(n + 1));
		ndist.assign(n + 1,0);
		wdist.assign(n + 1,0);
		up.assign(n + 1,v32(lgn,-1));
		wdist[1] = 0;
		ndist[1] = 0;
		up[1][0] = 1;
		dfs(1,0,g);
		for(int i = 1;i < lgn;i++)
			for(int j = 1;j < n + 1;j++)
				up[j][i] = up[up[j][i - 1]][i - 1];
	}
	int getLCA(int a,int b)
	{
		if(ndist[a] > ndist[b])
			swap(a,b);
		int diff = ndist[b] - ndist[a];
		for(int i = 0;i < lgn;i++)
			if(diff & (1 << i))
				b = up[b][i];
		if(a == b) return a;
		for(int i = lgn - 1;i >= 0;i--)
			if(up[a][i] != up[b][i])
				a = up[a][i],b = up[b][i];
		return up[a][0];
	}
	int getDist(int a,int b)
	{
		int ans = wdist[a] + wdist[b] - 2 * wdist[getLCA(a,b)];
		return ans;
	}
};

struct hld
{
	v32 id,head,npos,subsz;
	int chain,ptr;
	void dfs(int ii,int pp,graph &g)
	{
		subsz[ii] = 1;
		for(auto jj : g[ii])
			if(jj != pp)
			{
				dfs(jj,ii,g);
				subsz[ii] += subsz[jj];
			}
	}
	void decompose(int ii,int pp,graph &g)
	{
		if(head[chain] == -1) head[chain] = ii;
		id[ii] = chain;
		npos[ii] = ptr;
		if(pp)
		{
			int ec = weight[{ii,pp}].fi;
			int ew = weight[{ii,pp}].se;
			color[ec].push_back(ptr++);
			sum[ec].push_back(ew);
		}
		else
			ptr++;

		int n1 = 0,mx = 0;
		for(auto jj : g[ii])
			if(jj != pp && subsz[jj] > mx)
				n1 = jj,mx = subsz[jj];
		if(n1)
			decompose(n1,ii,g);
		for(auto jj : g[ii])
			if(jj != pp && jj != n1)
				chain++,decompose(jj,ii,g);
	}
	hld(int n,graph &g)
	{
		id.assign(n + 1,-1);
		head.assign(n + 1,-1);
		npos.assign(n + 1,-1);
		subsz.assign(n + 1,-1);
		chain = ptr = 1;
		dfs(1,0,g);
		decompose(1,0,g);
	}
};

int getSum(int clr,int i,int j)
{
	if(i > j)
		return 0;
	if(sum[clr].size() == 0)
		return 0;
	if(i <= 0)
		return sum[clr][j];
	else if(j < sum[clr].size())
		return (sum[clr][j] - sum[clr][i - 1]);
	else
		return getSum(clr,i,j - 1);
}

p32 compute(int u,int v,int clr,lca &L,hld &H)
{
	if(u == v)
		return {0,0};
	p32 ans = {0,0};
	while(true)
	{
		if(H.id[u] == H.id[v])
		{
			if(u == v) return ans;
			int f = H.npos[v] + 1;
			int s = H.npos[u];
			auto itr1 = lower_bound(color[clr].begin(),color[clr].end(),s + 1) - color[clr].begin();
			auto itr2 = lower_bound(color[clr].begin(),color[clr].end(),f) - color[clr].begin();
			ans.se += (itr1 - itr2);
			itr1--;
			ans.fi += getSum(clr,itr2,itr1);
			return ans;
		}
		int f = H.npos[H.head[H.id[u]]];
		int s = H.npos[u];
		auto itr1 = lower_bound(color[clr].begin(),color[clr].end(),s + 1) - color[clr].begin();
		auto itr2 = lower_bound(color[clr].begin(),color[clr].end(),f) - color[clr].begin();
		ans.se += (itr1 - itr2);
		itr1--;
		ans.fi += getSum(clr,itr2,itr1);
		u = L.up[H.head[H.id[u]]][0];
	}
}

int query(int u,int v,int x,int y,lca &L,hld &H)
{
	int l = L.getLCA(u,v);
	auto a1 = compute(u,l,x,L,H);
	auto a2 = compute(v,l,x,L,H);
	int d = L.getDist(u,v);
	int ans = d - (a1.fi + a2.fi) + y * (a1.se + a2.se);
	return ans;
}

int main()
{
	FASTIO;
	int n,m;
	cin >> n >> m;
	graph g(n + 1,s32());
	for(int i = 0;i < n - 1;i++)
	{
		int a,b,c,d;
		cin >> a >> b >> c >> d;
		g[a].insert(b);
		g[b].insert(a);
		weight[{a,b}] = {c,d};
		weight[{b,a}] = {c,d};
	}
	lca L(n,g);
	hld H(n,g);
	for(int i = 1;i < n + 1;i++)
	{
		if(sum[i].size())
			for(int j = 1;j < sum[i].size();j++)
				sum[i][j] += sum[i][j - 1];
	}
	while(m--)
	{
		int x,y,u,v;
		cin >> x >> y >> u >> v;
		cout << query(u,v,x,y,L,H) << ln;
	}
	return 0;
}


Measured memory_bytes: 58580