#include <bits/stdc++.h>
#define rep(i,n) for (int i = 0; i < (n); ++i)
using namespace std;
typedef long long ll;

const int MAXN = 1e5;
struct edge{int to,color,length;};
vector<vector<edge>> to(MAXN);
vector<int> G[MAXN];
struct LCA{
    static const int BITLEN_MAX = 30;
    vector<int> parent[BITLEN_MAX];
    vector<int> depth;
    int bitlen;

    void initialize(int N, const vector<int> edges[]){
        int root = 0;
        bitlen = 1;
        while((1<<bitlen) < N) bitlen += 1;
        for(int i=0; i<bitlen; i++) parent[i].resize(N);
        depth.resize(N, -1);

        dfs(root, -1, 0, edges);
        for(int k=0; k<bitlen-1; k++){
            for(int v=0; v<N; v++){
                if(depth[v] == -1) continue;
                if(parent[k][v] < 0){
                    parent[k+1][v] = -1;
                }else{
                    parent[k+1][v] = parent[k][parent[k][v]];
                }
            }
        }
    }

    void dfs(int v, int p, int d, const vector<int> edges[]){
        parent[0][v] = p;
        depth[v] = d;
        for(auto u : edges[v]){
            if(u != p) dfs(u, v, d+1, edges);
        }
    }

    int calc_lca(int u, int v){
        if(depth[u] > depth[v]) swap(u, v);
        for(int k=0; k<bitlen; k++){
            if( ((depth[v]-depth[u]) >> k) & 1 ) v = parent[k][v];
        }
        if(u == v) return u;
        for(int k=bitlen-1; k>=0; k--){
            if(parent[k][u] != parent[k][v]){
                u = parent[k][u];
                v = parent[k][v];
            }
        }
        return parent[0][u];
    }

    int calc_dist(int u, int v){
        int l = calc_lca(u, v);
        return depth[u] + depth[v] - depth[l]*2;
    }
};

vector<int> dist(MAXN); // 頂点iへの距離
vector<vector<int>> needcol(MAXN); // 頂点iに必要な色
vector<int> colcnt(MAXN); // 現在通った辺のうち色iの総和
vector<int> colsum(MAXN); // 現在通った辺のうち色iの総和
vector<map<int,int>> cnt(MAXN), sum(MAXN);
void 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;
}

int main(){
	
	int n,q;
	cin >> n >> q;
	
	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});
		G[a].push_back(b);
		G[b].push_back(a);
	}
	
	LCA lca;
	lca.initialize(n, G);
	
	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.calc_lca(u,v);
		needcol[u].push_back(x);
		needcol[v].push_back(x);
		needcol[lcauv].push_back(x);
		queries[i] = {x,y,u,v,lcauv};
	}

	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 0;
}


Measured memory_bytes: 67640