#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<ll, ll> P;
#define rep(i,n) for (ll i = 0; i < (n); ++i)
#define vcout(v) rep(i,v.size()) cout << v[i] << " "; cout << endl
#define mcout(m) rep(j,m.size()){vcout(m[j]);}

// 前処理 O(VlogV) クエリ処理 O(logV)
struct LCA{
	vector<vector<ll>> toTree;
	vector<ll> d;
	ll LOGV;
	vector<vector<ll>> par;

	// "to" must be tree
	LCA(vector<vector<ll>> to){
		this->toTree = to;
		this->d = vector<ll>(to.size(),-1);
		this->LOGV = log2l(to.size()) + 1;
		this->par = vector<vector<ll>>(LOGV, vector<ll>(to.size(),-1)); // 遡った結果rootを通り過ぎたら-1
		makeDepth(); 
		makePar();
	}

	void makeDepth(){
		queue<ll> q;
		q.push(0);
		d[0] = 0;
		while(!q.empty()){
			ll now = q.front();
			q.pop();
			for(ll child : toTree[now]){
				if(d[child] != -1) continue;
				d[child] = d[now] + 1;
				par[0][child] = now;
				q.push(child);
			}
		}
	}

	void makePar(){
		rep(i,LOGV-1) rep(j,par[0].size()){
			// par[i][j]: jから2^i上に遡った頂点
			if(par[i][j] >= 0) par[i+1][j] = par[i][par[i][j]];
		}
	}

	// return LCA of u and v
	ll get(ll u, ll v){

		// 深い方の頂点を浅い方の深さに合わせる
		if(d[u] > d[v]) swap(u,v);
		rep(i,LOGV){
			if((d[v] - d[u]) & (1ll<<i)) v = par[i][v];
		}
		if(u==v) return u;

		// LCAが見つかるまで二分探索で上に遡る
		for(ll i = LOGV-1; i >= 0; i--){
			if(par[i][u] != par[i][v]){
				u = par[i][u];
				v = par[i][v];
			}
		}

		return par[0][u];
	}
};

struct edge{int to,color,length;};

void mainsolve(){
	
	int n,q;
	cin >> n >> q;
	
	vector<vector<edge>> to(n);
	vector<vector<ll>> to2(n);
	rep(i,n-1){
		int a,b,c,d;
		cin >> a >> b >> c >> d;
		--a; --b; --c;
		to[a].push_back(edge{b,c,d});
		to[b].push_back(edge{a,c,d});
		to2[a].push_back(b);
		to2[b].push_back(a);
	}
	
	LCA lca(to2);
	
	vector<vector<int>> needcol(n); // 頂点iに必要な色
	vector<vector<int>> queries(q,vector<int>(5));
	rep(i,q){
		int x,y,u,v;
		cin >> x >> y >> u >> v;
		--x; --u; --v;
		
		int lcauv = lca.get(u,v);
		needcol[u].push_back(x);
		needcol[v].push_back(x);
		needcol[lcauv].push_back(x);
		queries[i] = {x,y,u,v,lcauv};
	}

	vector<int> dist(n); // 頂点iへの距離
	vector<int> colcnt(n); // 現在通った辺のうち色iの総和
	vector<int> colsum(n); // 現在通った辺のうち色iの総和
	vector<map<int,int>> cnt(n), sum(n);

	function<void(int,int)> dfs2 = [&](int v, int p){
		// 現在の総和を（必要がある場合だけ）memo
		for(auto col : needcol[v]){
			cnt[v][col] = colcnt[col];
			sum[v][col] = colsum[col];
		}
	
		for(auto e : to[v]){
			if(e.to == p) continue;
			dist[e.to] = dist[v] + e.length;
		
			// 進んだ分足す
			colcnt[e.color]++;
			colsum[e.color] += e.length;
		
			dfs2(e.to,v);
		
			// 戻るので引く
			colcnt[e.color]--;
			colsum[e.color] -= e.length;
		}
		return;
	};

	dfs2(0,-1);
	
	
	rep(i,q){
		int x,y,u,v,lcauv;
		x = queries[i][0];
		y = queries[i][1];
		u = queries[i][2];
		v = queries[i][3];
		lcauv = queries[i][4];
		
		int nowd = dist[u] + dist[v] - 2*dist[lcauv];
		int nowsum = sum[u][x] + sum[v][x] - 2*sum[lcauv][x];
		int nowcnt = cnt[u][x] + cnt[v][x] - 2*cnt[lcauv][x];
		cout << nowd - nowsum + nowcnt*y << endl;
	}
	return;
}

int main(){
	
	//ll TC;cin>>TC;rep(I,TC){cout<<"case:"<<I+1<<"---"<<endl; // comment out!
		mainsolve();
	//} // comment out!
	return 0;
}

Measured memory_bytes: 81520