#include <bits/stdc++.h>
#define syosu(x) fixed<<setprecision(x)
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> P;
typedef pair<double,double> pdd;
typedef pair<ll,ll> pll;
typedef vector<int> vi;
typedef vector<vi> vvi;
typedef vector<double> vd;
typedef vector<vd> vvd;
typedef vector<ll> vl;
typedef vector<vl> vvl;
typedef vector<string> vs;
typedef vector<P> vp;
typedef vector<vp> vvp;
typedef vector<pll> vpll;
typedef pair<int,P> pip;
typedef vector<pip> vip;
const int inf=1<<30;
const ll INF=1ll<<60;
const double pi=acos(-1);
const double eps=1e-8;
const ll mod=1e9+7;
const int dx[4]={-1,0,1,0},dy[4]={0,-1,0,1};

vi l,r;

class Segment_Tree{
	private:
	int n;
	vi date;
	public:
	void Init(int n_){
		n=1;
		while(n<n_) n*=2;
		date=vi(2*n-1);
	}
	void Update(int k,int x){
		k+=n-1;
		date[k]+=x;
		while(k>0){
			k=(k-1)/2;
			date[k]=date[k*2+1]+date[k*2+2];
		}
	}
	int Query(int a,int b){
		a+=n-1;b+=n-1;
		int m=0;
		while(a<b){
			if(a%2==0) m+=date[a++];
			if(b%2==0) m+=date[--b];
			a/=2;b/=2;
		}
		return m;
	}
	int Sum(int u,int v,int lca){
		return Query(0,l[u]+1)+Query(0,l[v]+1)-2*Query(0,l[lca]+1);
	}
	int Open(int k){return date[k+n-1];}
};

class Graph{
	private:
	int n;
	vvi g;
	int lv=20;
	vi rank;
	vvi Par;
	public:
	void LCA_dfs(int v,int t){
		rank[v]=t;
		for(auto u:g[v]) if(rank[u]==-1){
			Par[0][u]=v;
			LCA_dfs(u,t+1);
		}
	}
	void LCA_Prepare(){
		rank=vi(n,-1);
		Par=vvi(lv,vi(n));
		Par[0][0]=-1;
		LCA_dfs(0,0);
		for(int i=1;i<lv;i++) for(int j=0;j<n;j++){
			if(Par[i-1][j]<0) Par[i][j]=-1;
			else Par[i][j]=Par[i-1][Par[i-1][j]];
		}
	}
	int LCA(int s,int t){
		if(rank[s]>rank[t]) swap(s,t);
		for(int i=0;i<lv;i++) if((rank[t]-rank[s])>>i&1) t=Par[i][t];
		if(s==t) return s;
		for(int i=lv-1;i>=0;i--) if(Par[i][s]!=Par[i][t]){
			s=Par[i][s];
			t=Par[i][t];
		}
		return Par[0][s];
	}
	Graph(int v){
		n=v;
		g=vvi(v);
	}
	void add_edge(int s,int t){
		g[s].push_back(t);
		g[t].push_back(s);
	}
};

int n,q,id=0;
vvi g;
vi ei,res,D,dep;
vector<vip> a,b;

void dfs(int v,int p,int rank=0){
	l[v]=id++;
	dep[v]=rank;
	for(auto u:g[v]) if(u!=p) dfs(u,v,rank+1);
	r[v]=id;
}

int main(){
	cin>>n>>q;
	Graph G(n);
	g=vvi(n);
	l=r=ei=dep=vi(n);
	D=res=vi(q);
	a=b=vector<vip>(n);
	Segment_Tree st[3];
	for(int i=0;i<3;i++) st[i].Init(n+1);
	for(int i=1;i<n;i++){
		int u,v,c,d;
		cin>>u>>v>>c>>d;
		u--;v--;
		G.add_edge(u,v);
		g[u].push_back(v);
		g[v].push_back(u);
		b[c].push_back({d,{u,v}});
	}
	G.LCA_Prepare();
	dfs(0,-1);
	for(int i=0;i<q;i++){
		int u,v,c,d;
		cin>>c>>d>>u>>v;
		u--;v--;
		a[c].push_back({i,{u,v}});
		D[i]=d;
	}
	for(int i=0;i<n;i++) for(auto pp:b[i]){
		P p=pp.second;
		int d=pp.first,u=p.first,v=p.second;
		if(dep[u]<dep[v]) swap(u,v);
		st[0].Update(l[u],d);
		st[0].Update(r[u],-d);
	}
	for(int i=0;i<n;i++){
		for(auto pp:b[i]){
			P p=pp.second;
			int d=pp.first,u=p.first,v=p.second;
			if(dep[u]<dep[v]) swap(u,v);
			st[1].Update(l[u],d);
			st[1].Update(r[u],-d);
			st[2].Update(l[u],1);
			st[2].Update(r[u],-1);
		}
		for(auto pp:a[i]){
			P p=pp.second;
			int I=pp.first,u=p.first,v=p.second,lca=G.LCA(u,v);
			res[I]=st[0].Sum(u,v,lca)-st[1].Sum(u,v,lca)+D[I]*st[2].Sum(u,v,lca);
		}
		for(auto pp:b[i]){
			P p=pp.second;
			int d=pp.first,u=p.first,v=p.second;
			if(dep[u]<dep[v]) swap(u,v);
			st[1].Update(l[u],-d);
			st[1].Update(r[u],d);
			st[2].Update(l[u],-1);
			st[2].Update(r[u],1);
		}
	}
	for(auto i:res) cout<<i<<endl;
}

Measured memory_bytes: 38708