/*
数据不清空，爆零两行泪。
多测不读完，爆零两行泪。
边界不特判，爆零两行泪。
贪心不证明，爆零两行泪。
D P 顺序错，爆零两行泪。
大小少等号，爆零两行泪。
变量不统一，爆零两行泪。
越界不判断，爆零两行泪。
调试不注释，爆零两行泪。
溢出不 l l，爆零两行泪。
*/
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define pb push_back
#define X first
#define Y second
#define mp make_pair
const int N=100000,QU=100000;
int n,qu;
vector<pair<int,pair<int,int> > > nei[N+1];
struct query{int x,y,z,xx;}qry[QU+1];
vector<int> col[N];
int fa[N+1],sz[N+1],dep[N+1],wson[N+1],top[N+1],dfn[N+1],nowdfn;
int dis[N+1];
vector<pair<int,int> > buc[N];
void dfs1(int x=1){
	sz[x]=1;
	for(int i=0;i<nei[x].size();i++){
		int y=nei[x][i].X,c=nei[x][i].Y.X,len=nei[x][i].Y.Y;
		if(y==fa[x])continue;
		fa[y]=x;
		dep[y]=dep[x]+1;
		dis[y]=dis[x]+len;
		buc[c].pb(mp(y,len));
		dfs1(y);
		sz[x]+=sz[y];
		if(sz[y]>sz[wson[x]])wson[x]=y;
	}
}
void dfs2(int x=1,int t=1){
	dfn[x]=++nowdfn;
	top[x]=t;
	if(wson[x])dfs2(wson[x],t);
	for(int i=0;i<nei[x].size();i++){
		int y=nei[x][i].X;
		if(y==fa[x]||y==wson[x])continue;
		dfs2(y,y);
	}
}
struct segtree{
	struct node{int l,r,sum,cnt;}nd[N<<2];
	#define l(p) nd[p].l
	#define r(p) nd[p].r
	#define len(p) (r(p)-l(p)+1)
	#define sum(p) nd[p].sum
	#define cnt(p) nd[p].cnt
	void sprup(int p){sum(p)=sum(p<<1)+sum(p<<1|1);cnt(p)=cnt(p<<1)+cnt(p<<1|1);}
	void bld(int l=1,int r=n,int p=1){
		l(p)=l;r(p)=r;sum(p)=cnt(p)=0;
		if(l==r)return;
		int mid=l+r>>1;
		bld(l,mid,p<<1);bld(mid+1,r,p<<1|1);
	}
	void init(){bld();}
	void add(int x,int v1,int v2,int p=1){
		if(l(p)==r(p)){sum(p)+=v1;cnt(p)+=v2;return;}
		int mid=l(p)+r(p)>>1;
		add(x,v1,v2,p<<1|(x>mid));
		sprup(p);
	}
	int _sum(int l,int r,int p=1){
		if(l<=l(p)&&r>=r(p))return sum(p);
		int mid=l(p)+r(p)>>1,res=0;
		if(l<=mid)res+=_sum(l,r,p<<1);
		if(r>mid)res+=_sum(l,r,p<<1|1);
		return res;
	}
	int _cnt(int l,int r,int p=1){
		if(l<=l(p)&&r>=r(p))return cnt(p);
		int mid=l(p)+r(p)>>1,res=0;
		if(l<=mid)res+=_cnt(l,r,p<<1);
		if(r>mid)res+=_cnt(l,r,p<<1|1);
		return res;
	}
	#undef sum
	#undef cnt
}segt;
int lca(int x,int y){
	while(top[x]!=top[y]){
		if(dep[top[x]]<dep[top[y]])swap(x,y);
		x=fa[top[x]];
	}
	if(dep[x]<dep[y])swap(x,y);
	return y;
}
void add(int x,int v1,int v2){segt.add(dfn[x],v1,v2);}
int sum(int x,int y){
	int res=0;
	while(top[x]!=top[y]){
		if(dep[top[x]]<dep[top[y]])swap(x,y);
		res+=segt._sum(dfn[top[x]],dfn[x]);
		x=fa[top[x]];
	}
	if(dep[x]<dep[y])swap(x,y);
	return res+segt._sum(dfn[y]+1,dfn[x]);
}
int cnt(int x,int y){
	int res=0;
	while(top[x]!=top[y]){
		if(dep[top[x]]<dep[top[y]])swap(x,y);
		res+=segt._cnt(dfn[top[x]],dfn[x]);
		x=fa[top[x]];
	}
	if(dep[x]<dep[y])swap(x,y);
	return res+segt._cnt(dfn[y]+1,dfn[x]);
}
int ans[QU+1];
signed main(){
	cin>>n>>qu;
	for(int i=1;i<n;i++){
		int x,y,z,xx;
		scanf("%lld%lld%lld%lld",&x,&y,&z,&xx);
		nei[x].pb(mp(y,mp(z,xx)));nei[y].pb(mp(x,mp(z,xx)));
	}
	dfs1();dfs2();
	segt.init();
	for(int i=1;i<=qu;i++){
		scanf("%lld%lld%lld%lld",&qry[i].x,&qry[i].y,&qry[i].z,&qry[i].xx);
		col[qry[i].x].pb(i);
	}
	for(int i=1;i<n;i++){
		for(int j=0;j<buc[i].size();j++)add(buc[i][j].X,buc[i][j].Y,1);
		for(int j=0;j<col[i].size();j++){
			int x=col[i][j];
			ans[x]=dis[qry[x].z]+dis[qry[x].xx]-2*dis[lca(qry[x].z,qry[x].xx)]-sum(qry[x].z,qry[x].xx)+qry[x].y*cnt(qry[x].z,qry[x].xx);
		}
		for(int j=0;j<buc[i].size();j++)add(buc[i][j].X,-buc[i][j].Y,-1);
	}
	for(int i=1;i<=qu;i++)printf("%lld\n",ans[i]);
	return 0;
}
/*1
5 3
1 2 1 10
1 3 2 20
2 4 4 30
5 2 1 40
1 100 1 4
1 100 1 5
3 1000 3 4
*/

Measured memory_bytes: 43508