#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace std;
typedef long long ll;
typedef pair<int,int> P;
typedef pair<int,P> P1;
typedef pair<P,P> P2;
#define pu push
#define pb push_back
#define mp make_pair
#define eps 1e-7
#define INF 1000000000
#define mod 1000000007
#define fi first
#define sc second
#define rep(i,x) for(int i=0;i<x;i++)
#define repn(i,x) for(int i=1;i<=x;i++)
#define SORT(x) sort(x.begin(),x.end())
#define ERASE(x) x.erase(unique(x.begin(),x.end()),x.end())
#define POSL(x,v) (lower_bound(x.begin(),x.end(),v)-x.begin())
int n,q;
vector<P1>edge[100005];
vector<P2>query[100005];
int dep[100005],up[100005][20];
int calc_lca(int ss,int t){
	if(dep[ss]>dep[t]) swap(ss,t);
	rep(i,19){
		if((((dep[t]-dep[ss])>>i)&1)){
			t = up[t][i];
		}
	}
	if(ss==t) return ss;
	for(int i=19;i>=0;i--){
		if(up[ss][i]!=up[t][i]){
			ss = up[ss][i];
			t = up[t][i];
		}
	}
	return up[ss][0];
}
class segtree
{
public:
	#define s (1<<17)
	ll seg[s*2];
	ll lazy[s*2];
	void lazy_evaluate(int k)
	{
		if(k*2+2>=s*2) return ;
		lazy[k*2+2]+=lazy[k];
		lazy[k*2+1]+=lazy[k];
		seg[k*2+2]+=lazy[k];
		seg[k*2+1]+=lazy[k];
		lazy[k]=0;
	}
	ll update(int beg,int end,int idx,int lb,int ub,ll num)
	{
		if(ub<beg||end<lb)
		{
			return seg[idx];
		}
		if(beg<=lb&&ub<=end)
		{
			lazy[idx]+=num;
			seg[idx]+=num;
			return seg[idx];
		}
		if(lazy[idx])
		{
			lazy_evaluate(idx);
		}
		return seg[idx]=max(update(beg,end,idx*2+1,lb,(lb+ub)/2,num),update(beg,end,idx*2+2,(lb+ub)/2+1,ub,num));
	}
	ll query(int beg,int end,int idx,int lb,int ub)
	{
		if(ub<beg||end<lb)
		{
			return -1000000000000000000LL;
		}
		if(beg<=lb&&ub<=end)
		{
			return seg[idx];
		}
		if(lazy[idx])
		{
			lazy_evaluate(idx);
		}
		return max(query(beg,end,idx*2+1,lb,(lb+ub)/2),query(beg,end,idx*2+2,(lb+ub)/2+1,ub));
	}
}kaede;
int in[100005],out[100005],nxt;
vector<P>ch[100005];
void dfs(int v,int u,ll V){
	if(u == -1) dep[v] = 0; else dep[v] = dep[u]+1;
	up[v][0] = u; kaede.update(nxt,nxt,0,0,s-1,V);
	in[v] = nxt++;
	rep(i,edge[v].size()){
		if(edge[v][i].fi == u) continue;
		dfs(edge[v][i].fi,v,V+edge[v][i].sc.sc);
		ch[edge[v][i].sc.fi].pb(P(edge[v][i].fi,edge[v][i].sc.sc));
	}
	out[v] = nxt-1;
}
ll ans1[100005],ans2[100005];
int main(){
	cin >> n >> q;
	rep(i,n-1){
		int a,b,c,d; cin >> a >> b >> c >> d;
		edge[a].pb(P1(b,mp(c,d)));
		edge[b].pb(P1(a,mp(c,d)));
	}
	rep(i,q){
		int x,y,u,v; cin >> x >> y >> u >> v;
		query[x].pb(P2(mp(i,y),mp(u,v)));
	}
	dfs(1,-1,0);
	rep(j,18)repn(i,n){
		if(up[i][j]==-1) up[i][j+1] =-1;
		else up[i][j+1] =up[up[i][j]][j];
	}
	for(int i=1;i<=n-1;i++){
		rep(j,ch[i].size()){
			kaede.update(in[ch[i][j].fi],out[ch[i][j].fi],0,0,s-1,-ch[i][j].sc);
		}
		rep(j,query[i].size()){
			int e = calc_lca(query[i][j].sc.fi,query[i][j].sc.sc);
			ans1[query[i][j].fi.fi] += kaede.query(in[query[i][j].sc.fi],in[query[i][j].sc.fi],0,0,s-1);
			ans1[query[i][j].fi.fi] += kaede.query(in[query[i][j].sc.sc],in[query[i][j].sc.sc],0,0,s-1);
			ans1[query[i][j].fi.fi] -= 2LL*kaede.query(in[e],in[e],0,0,s-1);
		}
		rep(j,ch[i].size()){
			kaede.update(in[ch[i][j].fi],out[ch[i][j].fi],0,0,s-1,1);
		}
		rep(j,query[i].size()){
			int e = calc_lca(query[i][j].sc.fi,query[i][j].sc.sc);
			ans2[query[i][j].fi.fi] += kaede.query(in[query[i][j].sc.fi],in[query[i][j].sc.fi],0,0,s-1);
			ans2[query[i][j].fi.fi] += kaede.query(in[query[i][j].sc.sc],in[query[i][j].sc.sc],0,0,s-1);
			ans2[query[i][j].fi.fi] -= 2LL*kaede.query(in[e],in[e],0,0,s-1);
			ans2[query[i][j].fi.fi] = ans1[query[i][j].fi.fi] + (ans2[query[i][j].fi.fi]-ans1[query[i][j].fi.fi])*query[i][j].fi.sc;
		}
		rep(j,ch[i].size()){
			kaede.update(in[ch[i][j].fi],out[ch[i][j].fi],0,0,s-1,ch[i][j].sc-1);
		}
	}
	rep(i,q){
		cout << ans2[i] << endl;
	}
}

Measured memory_bytes: 38388