#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#define N 200005
using namespace std;
int n,Q,a,b,c,d,x,y,cnt,head[N];
int tot,fa[N],deep[N],size[N],son[N],top[N],pos[N],re[N],co[N],di[N];
struct node{
	int to,next,c,d;
}e[N<<1];
void insert(int u,int v,int c,int d){
	e[++cnt].to=v;e[cnt].next=head[u];e[cnt].c=c;e[cnt].d=d;head[u]=cnt;
	e[++cnt].to=u;e[cnt].next=head[v];e[cnt].c=c;e[cnt].d=d;head[v]=cnt;
}
struct tree{
	int lc,rc,size,sum;
}t[N*20];
int sz;
class Segment_T{
	int root;
	void pushup(int x){
		int lc=t[x].lc,rc=t[x].rc;
		t[x].size=t[lc].size+t[rc].size;
		t[x].sum=t[lc].sum+t[rc].sum;
	}
	void build(int &x,int l,int r){
		x=++sz;
		if(l==r){
			t[x].size=1;t[x].sum=di[re[l]];
			return;
		}
		int mid=l+r>>1;
		build(t[x].lc,l,mid);
		build(t[x].rc,mid+1,r);
		pushup(x);
		//cout<<l<<" "<<r<<" "<<t[x].size<<" "<<t[x].sum<<endl;
	}
	void insert(int &x,int l,int r,int p){
		if(!x) x=++sz;
		t[x].size++;t[x].sum+=di[re[p]];
		//cout<<x<<" "<<l<<" "<<r<<" "<<p<<endl;
		if(l==r){
			return;
		}
		int mid=l+r>>1;
		if(p<=mid) insert(t[x].lc,l,mid,p);
		else insert(t[x].rc,mid+1,r,p);
	}
	int asksize(int x,int l,int r,int L,int R){
		if(L<=l && R>=r) return t[x].size;
		int mid=l+r>>1,tmp=0;
		if(L<=mid) tmp=asksize(t[x].lc,l,mid,L,R);
		if(R>mid) tmp+=asksize(t[x].rc,mid+1,r,L,R);
		return tmp;
	}
	int asksum(int x,int l,int r,int L,int R){
		if(L<=l && R>=r) return t[x].sum;
		int mid=l+r>>1,tmp=0;
		if(L<=mid) tmp=asksum(t[x].lc,l,mid,L,R);
		if(R>mid) tmp+=asksum(t[x].rc,mid+1,r,L,R);
		return tmp;
	}
public:
	void Build(){
		build(root,1,n);
	}
	void Insert(int p){
		insert(root,1,n,p);
	}
	int Asksize(int l,int r){
		//cout<<root<<" "<<l<<" "<<r<<endl;
		if(l>r) return 0;
		return asksize(root,1,n,l,r);
	}
	int Asksum(int l,int r){
		if(l>r) return 0;
		return asksum(root,1,n,l,r);
	}
}T[N];
void dfs1(int x){
	size[x]=1;
	deep[x]=deep[fa[x]]+1;
	for(int i=head[x];i;i=e[i].next)
		if(e[i].to^fa[x]){
			fa[e[i].to]=x;
			co[e[i].to]=e[i].c;
			di[e[i].to]=e[i].d;
			dfs1(e[i].to);
			size[x]+=size[e[i].to];
			if(size[son[x]]<size[e[i].to]) son[x]=e[i].to;
		}
}
void dfs2(int x,int chain){
	top[x]=chain;
	pos[x]=++tot;
	re[tot]=x;
	//cout<<x<<" "<<tot<<" "<<co[x]<<" "<<di[x]<<endl;
	if(!son[x]) return;
	dfs2(son[x],chain);
	for(int i=head[x];i;i=e[i].next)
		if(e[i].to^fa[x] && e[i].to^son[x])
			dfs2(e[i].to,e[i].to);
}
void dfs3(int x){
	if(co[x])
		T[co[x]].Insert(pos[x]);
	for(int i=head[x];i;i=e[i].next)
		if(e[i].to^fa[x])
			dfs3(e[i].to);
}
int query1(int x,int y){
	int ans=0;
	while(top[x]^top[y]){
		//cout<<x<<" "<<y<<endl;
		if(deep[fa[top[x]]]<deep[fa[top[y]]]) swap(x,y);
		ans+=T[0].Asksum(pos[top[x]],pos[x]);
		x=fa[top[x]];
	}
	if(deep[x]>deep[y]) swap(x,y);
	ans+=T[0].Asksum(pos[x]+1,pos[y]);
	return ans;
}
int query2(int x,int y,int a,int b){
	int cnt=0,ans=0;
	while(top[x]^top[y]){
		if(deep[fa[top[x]]]<deep[fa[top[y]]]) swap(x,y);
		cnt+=T[a].Asksize(pos[top[x]],pos[x]);
		ans+=T[a].Asksum(pos[top[x]],pos[x]);
		x=fa[top[x]];
	}
	if(deep[x]>deep[y]) swap(x,y);
	cnt+=T[a].Asksize(pos[x]+1,pos[y]);
	ans+=T[a].Asksum(pos[x]+1,pos[y]);
	//cout<<cnt<<" "<<ans<<endl;
	return cnt*b-ans;
}
int main(){
	scanf("%d%d",&n,&Q);
	for(int i=1;i<n;i++){
		scanf("%d%d%d%d",&a,&b,&c,&d);
		insert(a,b,c,d);
	}
	dfs1(1);
	dfs2(1,1);
	T[0].Build();
	dfs3(1);
	while(Q--){
		scanf("%d%d%d%d",&x,&y,&a,&b);
		printf("%d\n",query1(a,b)+query2(a,b,x,y));
	}
	return 0;
}


Measured memory_bytes: 40704