#include<bits/stdc++.h>
#define N 100005
#define pb push_back
#define pii pair<int,int>
#define fi first
#define se second
#define mp make_pair
using namespace std;
template<typename T>
inline void in(T &x)
{
	x=0;
	char c=getchar();
	while(c<'0'||c>'9')c=getchar();
	while(c>='0'&&c<='9')x=(x<<1)+(x<<3)+(c^48),c=getchar();
}
int n,m,ans[N],dep[N],success[N],dfn[N],head[N],a[N],b[N],c[N],d[N],fa[N],x[N],y[N],u[N],V[N],dfsc;
vector<int> v[N],C[N],D[N];
inline int lower_point(int x,int y){return dep[x]>dep[y]?x:y;}
struct data
{
	int sum,num;
	data(int _sum=0,int _num=0):sum(_sum),num(_num){}
}tree[N<<1];
inline int ID(int l,int r){return (l+r)|(l!=r);}
int dfs(int from,int f)
{
//	puts("in_dfs");
	dep[from]=dep[f]+1;
	fa[from]=f;
	int sz=1,mx=0,cur;
	for(int i=0;i<v[from].size();++i)
	{
		int to=v[from][i];
		if(to==f)continue;
		sz+=(cur=dfs(to,from));
		if(cur>mx)
		{
			mx=cur;
			success[from]=to;
		}
	}
	return sz;
}
void make_chain(int from,bool in_chain)
{
	dfn[from]=++dfsc;
	if(in_chain)head[from]=head[fa[from]];
	else head[from]=from;
	if(success[from])make_chain(success[from],1);
	for(int i=0;i<v[from].size();++i)
	{
		int to=v[from][i];
		if(to==success[from]||to==fa[from])continue;
		make_chain(to,0);
	}
}
inline void push_up(int k,int l,int r)
{
	int mid=l+r>>1,ls=ID(l,mid),rs=ID(mid+1,r);
	tree[k].sum=tree[ls].sum+tree[rs].sum;
	tree[k].num=tree[ls].num+tree[rs].num;
}
void update(int k,int l,int r,int p,int val,int num)
{
//	puts("in_update");
//	cout<<"l:"<<l<<" r:"<<r<<endl;
	if(l==r)
	{
		tree[k].sum=val;
		tree[k].num=num;
		return;
	}
	int mid=l+r>>1;
	if(p<=mid)update(ID(l,mid),l,mid,p,val,num);
	else update(ID(mid+1,r),mid+1,r,p,val,num);
	push_up(k,l,r);
}
int cnt=0;
void query(int k,int l,int r,int L,int R,int &sum,int &num)
{
//	puts("in_query");
//	cout<<"l:"<<l<<" r:"<<r<<" L:"<<L<<" R:"<<R<<endl;
//	++cnt;
//	if(cnt==10)while(1);
	if(L<=l&&r<=R)
	{
		sum+=tree[k].sum;
		num+=tree[k].num;
		return;
	}
	int mid=l+r>>1;
	if(L<=mid)query(ID(l,mid),l,mid,L,R,sum,num);
	if(mid<R)query(ID(mid+1,r),mid+1,r,L,R,sum,num);
}
void Query(int x,int y,int &sum,int &num)
{
//	puts("in_Query");
	while(head[x]!=head[y])
	{
		if(dep[head[x]]<dep[head[y]])swap(x,y);
		query(ID(1,dfsc),1,dfsc,dfn[head[x]],dfn[x],sum,num);
//		cout<<"sum:"<<sum<<endl;
		x=fa[head[x]];
	}
	if(dep[x]>dep[y])swap(x,y);
	if(x!=y)query(ID(1,dfsc),1,dfsc,dfn[x]+1,dfn[y],sum,num);
}
int main()
{
	in(n);in(m);
	for(int i=1;i<n;++i)
	{
		in(a[i]);in(b[i]);in(c[i]);in(d[i]);
		v[a[i]].pb(b[i]);
		v[b[i]].pb(a[i]);
		C[c[i]].pb(i);
	}
	dfs(1,0);
	make_chain(1,0);
	for(int i=0;i<m;++i)
	{
		in(x[i]);in(y[i]);in(u[i]);in(V[i]);
		D[x[i]].pb(i);
	}
	for(int i=1;i<n;++i)
	{
		int t=lower_point(a[i],b[i]);
//		cout<<"d:"<<d[i]<<endl;
//		cout<<"dfn:"<<dfn[t]<<endl;
		update(ID(1,dfsc),1,dfsc,dfn[t],d[i],0);
	}
	int _sum=0,_num=0;
	query(ID(1,dfsc),1,dfsc,1,dfsc,_sum,_num);
//	cout<<"dfsc:"<<dfsc<<endl;
//	cout<<tree[ID(1,5)].sum<<endl;
	for(int i=0;i<m;++i)
	{
		int tmp=0;
		Query(u[i],V[i],ans[i],tmp);
//		cout<<"ans:"<<ans[i]<<endl;
	}
	for(int i=0;i<(N<<1);++i)tree[i].sum=tree[i].num=0;
	for(int i=1;i<n;++i)
	{
		for(int j=0;j<C[i].size();++j)
		{
			int t=C[i][j];
			update(ID(1,dfsc),1,dfsc,dfn[lower_point(a[t],b[t])],d[t],1);
		}
		for(int j=0;j<D[i].size();++j)
		{
			int t=D[i][j];
			int sum=0,num=0;
			Query(u[t],V[t],sum,num);
			ans[t]-=sum;
			ans[t]+=num*y[t];
		}
		for(int j=0;j<C[i].size();++j)
		{
			int t=C[i][j];
			update(ID(1,dfsc),1,dfsc,dfn[lower_point(a[t],b[t])],0,0);
		}
	}
	for(int i=0;i<m;++i)printf("%d\n",ans[i]);
	return 0;
}

Measured memory_bytes: 28656