#include <string>
#include <vector>
#include <sstream>
#include <iostream>
#include <algorithm>
#include <map>
#include <list>
#include <set>
#include <numeric>
#include <queue>
#include <stack>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <cctype>
#include <cstring>
#include <climits>
#include <cfloat>
#include <ctime>
#include <complex>
#include <cassert>
#include <array>
#include <bitset> 
#include <unordered_map>
using namespace std;
typedef long long LL;
typedef pair<LL,LL> P;
typedef array<LL,3> A;

template <typename T, class Operator, T def>
struct SegTree
{
	vector<T> tree;
	Operator op;
	int s;
	void init(int size, Operator opr)
	{
		s=size;
		op=opr;
		tree.clear();
		tree.resize(4*size,def);
	}

	void add(int pos, T value)
	{
		add(pos,value,0,s,0);
	}

	// [low, hi) 
	void add(int pos, T value, int low, int hi, int i)
	{
		if(low+1==hi){
			tree[i]=value;
		}
		else if(low+1<hi){
			int mid=(low+hi)/2;
			if(pos<mid){
				add(pos,value,low,mid,2*i+1);
			}
			else{
				add(pos,value,mid,hi,2*i+2);
			}
			tree[i]=op(tree[2*i+1],tree[2*i+2]);
		}
	}

	// [a,b)
	T get(int a, int b)
	{
		return get(a,b,0,s,0);
	}

	T get(int a, int b, int low, int hi, int i)
	{
		if(hi<=a||b<=low||hi<=low){
			return def;
		}
		if(a<=low&&hi<=b){
			return tree[i];
		}
		int mid=(low+hi)/2;
		return op(get(a,b,low,mid,2*i+1),get(a,b,mid,hi,2*i+2));
	}

	template<class Pred> int maxIndex(int a, int b, Pred pr)
	{
		return minIndex(a,b,0,s,0,pr);
	}

	template<class Pred> int minIndex(int a,int b,int low, int hi, int i,Pred pr)
	{
		if(hi<=a||b<=low||hi<=low){
			return -1;
		}
		if(a<=low&&hi<=b&&!pr(tree[i])){
			return -1;
		}
		if(low+1==hi){
			return low;
		}
		int mid=(low+hi)/2;
		int p=minIndex(a,b,low,mid,2*i+1,pr);
		if(p!=-1){
			return p;
		}
		return minIndex(a,b,mid,hi,2*i+2,pr);
	}
	
#if 0
	void debug()
	{
		for(int i=0;i<tree.size();i++){
			cout << tree[i] << " ";
		}
		cout << endl;
	}
#endif
};

struct LCA
{
	struct Min
	{
		int operator() (int a, int b){
			return min(a,b);
		}
	};
	vector<vector<int> > children;
	vector<int> item;
	vector<int> pos;
	SegTree<int,Min,INT_MAX> seg;
	int c=0;
	void init(int s){
		children.clear();
		children.resize(s);
		seg.init(2*s,Min());
		pos.resize(s);
		c=0;
	}
	void add(int a,int b){
		children[a].push_back(b);
		//cerr << a << ", " << b << endl;
	}
	void build(int p)
	{
		int d=item.size();
		item.push_back(p);
		for(int i=0;i<max((size_t)1,children[p].size());i++){
			if(children[p].size()<=1||i>0){
				pos[p]=c;
				seg.add(c,d);
				c++;
			}
			if(i<children[p].size()){
				build(children[p][i]);
			}
		}
	}
	int get(int a,int b){
		//cerr << a << ", "<< b << ", " << seg.s << ", " << pos[a] << ", " << pos[b] << endl;
		int d=seg.get(min(pos[a],pos[b]),max(pos[a],pos[b])+1);
		return item[d];
	}
};


const int L=1e5+1;
vector<A> es[L];
vector<P> cs[L];
vector<P> ds[L];
int depth[L];
int ts[L];
LCA lca;
void dfs(int r,int& t){
	//cerr << r << endl;
	for(auto a:es[r]){
		if(ts[a[0]])continue;
		int b=a[0];
		lca.add(r,b);
		t++;
		ts[b]=t;
		int c=a[1];
		int d=a[2];
		depth[b]=d+depth[r];
		cs[c].push_back(P(t,cs[c].back().second+1));
		ds[c].push_back(P(t,ds[c].back().second+d));
		dfs(b,t);
		t++;
		cs[c].push_back(P(t,cs[c].back().second-1));
		ds[c].push_back(P(t,ds[c].back().second-d));
	}
}
int g(int k,vector<P>& vs){
	auto it=upper_bound(vs.begin(),vs.end(),P(ts[k]+1,-1));
	it--;
	return it->second;
}
int main(){
	int N,Q;
	cin >> N >> Q;
	for(int i=0;i<N-1;i++){
		int a,b,c,d;
		cin >> a >> b >> c >> d;
		a--;
		b--;
		c--;
		es[a].push_back({b,c,d});
		es[b].push_back({a,c,d});
	}
	for(int i=0;i<=N-1;i++){
		cs[i].push_back(P(0,0));
		ds[i].push_back(P(0,0));
	}
	lca.init(N);
	int t=1;
	ts[0]=1;
	dfs(0,t);
	lca.build(0);
	for(int i=0;i<Q;i++){
		int x,y,u,v;
		cin >> x >> y >> u >> v;
		x--;u--;v--;
		int r=lca.get(u,v);
		//cerr << u << ", " << v << ", " << r << endl;
		//cerr << depth[u] << ", " << depth[v] << ", " << depth[r] << endl;
		//cerr << g(u,cs[x]) << ", " << g(v,cs[x]) << ", " << g(r,cs[x]) << endl;
		LL ret=depth[u]+depth[v]-2*depth[r]
			-(g(u,ds[x])+g(v,ds[x])-2*g(r,ds[x]))+
			y*(g(u,cs[x])+g(v,cs[x])-2*g(r,cs[x]));
		cout << ret << endl;
	}

    return 0;
}


Measured memory_bytes: 48228