#include <bits/stdc++.h>

using namespace std;

#define REP(i,n) for(ll (i) = (0);(i) < (n);++i)
#define REV(i,n) for(ll (i) = (n) - 1;(i) >= 0;--i)
#define PB push_back
#define EB emplace_back
#define MP make_pair
#define FI first
#define SE second
#define SHOW1d(v,n) {REP(WW,n)cerr << v[WW] << ' ';cerr << endl << endl;}
#define SHOW2d(v,WW,HH) {REP(W_,WW){REP(H_,HH)cerr << v[W_][H_] << ' ';cerr << endl;}cerr << endl;}
#define ALL(v) v.begin(),v.end()
#define Decimal fixed<<setprecision(20)
#define INF 1000000000
#define LLINF 1000000000000000000LL
#define MOD 998244353

typedef long long ll;
typedef pair<ll,ll> P;

struct UF{
	vector<int> par; // 親
	vector<int> sz; // 数
	// 初期化
	UF(int n):par(n),sz(n) {
		for(int i = 0; i < n; i++){
			par[i] = i;sz[i] = 1;
		}
	}
	// 木の根を求める
	int find(int x) {
		if (par[x] == x) return x;
		else return par[x] = find(par[x]);
	}
	// xとyの属する集合を併合
	void unite(int x, int y) {
		x = find(x); y = find(y);
		if (x == y) return;
		par[x] = y;
		sz[x] += sz[y];
	}
	// xとyが同じ集合ならtrue
	bool same(int x, int y) { return find(x) == find(y); }
	int size(int n){return sz[find(n)];}
};

//普通のLCA(UFと一緒に)
struct LCA{
	//隣接リスト、(相手、重み)
	vector<vector<pair<int,int> > > g;
	//親
	vector<vector<int> > parent;
	//深さ
	vector<int> depth;
	UF uf;
	int sz;
	vector<bool> inited;

	LCA(int n):g(n),parent(20,vector<int>(n)),
	inited(n,false),depth(n),uf(n){sz = n;}

	//辺の追加(点、点、重み)
	void add_edge(int u,int v,int w = 1){
		if(uf.same(u,v))return;
		g[v].PB(MP(u,w));
		g[u].PB(MP(v,w));
		uf.unite(v,u);
	}

	void dfs(int v,int p,int d){
		inited[v] = true;
		parent[0][v] = p;
		depth[v] = d;
		REP(i,g[v].size()){
			if(g[v][i].FI != p)dfs(g[v][i].FI,v,d+1);
		}
	}

	void init(){
		REP(i,sz)if(!inited[i])dfs(uf.find(i),-1,0);
		REP(k,19){
			REP(i,sz){
				if(parent[k][i] < 0)parent[k+1][i] = -1;
				else parent[k+1][i] = parent[k][parent[k][i]];
			}
		}
	}

	int ret_lca(int a,int b){

		if(!uf.same(a,b))return -1;

		if(depth[a] > depth[b])swap(a,b);
		REP(k,20){
			if((depth[b] - depth[a])>>k&1)b = parent[k][b];
		}
		if(a == b)return a;

		for(int k = 19;k >= 0;k--){
			if(parent[k][a] != parent[k][b])
			{
				a = parent[k][a];
				b = parent[k][b];
			}
		}
		return parent[0][a];
	}

};

/*
0-index
functionの中を書いて使う
segtree<ll> seg(n, [](ll a, ll b){return a + b;}, 0);
*/
template<typename T>
struct segtree{
	int n;
	vector<T> dat;
	T ZERO;
	function<T(T,T)> func;//要素と要素をマージする関数

	segtree(int n_, function<T(T,T)> func_, T zero):func(func_), ZERO(zero){
	  n = 1;
	  while(n < n_)n*=2;
	  dat.resize(2*n);
	  for(int i = 0;i < 2*n;i++)dat[i] = ZERO;
	}

	void update(int k, T a){
	  k += n - 1;dat[k] = a;
	  while(k > 0){
		k = (k-1)/2;
		dat[k] = func(dat[k*2+1],dat[k*2+2]);
	  }
	}

	void set(int k, T a) {
		k += n - 1;dat[k] = a;
	}

	void build(){
		for(int i = n - 2;i >= 0;i--){
			dat[i] = func(dat[2 * i + 1], dat[2 * i + 2]);
		}
	}

	T get(int k){return dat[k+n-1];}

	T que(int a,int b){
		T L = ZERO,R = ZERO;
		int A = a + n - 1;
		int B = b + n - 1;
		while(A < B){
			if((A & 1) == 0)L = func(L,dat[A++]);
            if((B & 1) == 0)R = func(dat[--B],R);
            A = A >> 1;
            B = B >> 1;
		}
		return func(L,R);
	}
};

vector<vector<pair<ll, P>>> v(111111);
vector<vector<P>> color_edge(111111);
vector<int> place(111111);
vector<vector<pair<P, P>>> que(111111);
segtree<ll> seg(222222, [](ll a, ll b){return a + b;}, 0);

void dfs(int now, int pre, P e, int &pla){
	seg.update(pla, e.SE);
	color_edge[e.FI].EB(pla, e.SE);
	pla++;
	place[now] = pla;
	REP(i, v[now].size()){
		if(v[now][i].FI == pre)continue;
		dfs(v[now][i].FI, now, v[now][i].SE, pla);
	}
	seg.update(pla, -e.SE);
	color_edge[e.FI].EB(-pla, -e.SE);
	pla++;

	return;
}

int main(){
	cin.tie(0);cout.tie(0);ios::sync_with_stdio(false);

	ll n, q;cin >> n >> q;
	LCA lca(111111);
	REP(i, n-1){
		int a, b, c, d;cin >> a >> b >> c >> d;
		a--;b--;
		v[a].EB(b, MP(c, d));
		v[b].EB(a, MP(c, d));
		lca.add_edge(a, b);
	}

	lca.init();
	ll parent = 0;
	REP(i, n){
		parent = lca.ret_lca(parent, i);
	}

	int pla = 0;
	dfs(parent, -1, MP(110000, 0), pla);

	REP(i, q){
		int a, b, c, d;cin >> a >> b >> c >> d;
		c--;d--;
		que[a].PB(MP(MP(i, b), MP(c, d)));
	}

	vector<P> ans;

	REP(i, 111111){
		REP(j, color_edge[i].size()){
			if(color_edge[i][j].FI < 0){
				seg.update(-color_edge[i][j].FI, -1000000000000);
			}
			else {
				seg.update(color_edge[i][j].FI, 1000000000000);
			}
		}

		REP(j, que[i].size()){
			int a = que[i][j].SE.FI;
			int b = que[i][j].SE.SE;
			ll w = que[i][j].FI.SE;
			int id = que[i][j].FI.FI;
			int pare = lca.ret_lca(a, b);
			ll tmp = seg.que(0, place[a]) + seg.que(0, place[b]) - 2 * seg.que(0, place[pare]);
			ll ama = tmp / 1000000000000;
			ll noko = tmp % 1000000000000;
			//cout << a << " " << b << " " << pare << " " << id << " " << ama << " " << noko << endl;
			ans.EB(id, ama * w + noko);
		}

		REP(j, color_edge[i].size()){
			seg.update(abs(color_edge[i][j].FI), color_edge[i][j].SE);
		}

	}

	sort(ALL(ans));
	REP(i, ans.size()){
		cout << ans[i].SE << endl;
	}

	return 0;
}


Measured memory_bytes: 58052