//#pragma comment(linker, "/stack:200000000")
//#pragma GCC optimize("Ofast")
//#pragma GCC target("sse,sse2,sse3,ssse3,sse4,avx,avx2")

#include <vector>
#include <stdio.h>
#include <iostream>
#include <unordered_set>
#include <algorithm>
#include <bitset>
#include <set>
#include <map>
#include <random>
#include <time.h>
#include <cassert>

#define prev askdnsajd
#define rank asasdmdnasd
#define next lsjndajbs
#define hash asmdklansd
#define index asdklnas
#define right sld
#define left sldl
using namespace std;

typedef long long ll;
typedef long double dbl;

template<class T>
void print(vector<T> s){
    for (T x : s)
        cout << x << " ";
    cout << endl;
}

const int maxn = 1e5 + 7;

int color[maxn], tin[maxn];
vector<int> euler;
vector<int> s[maxn];
vector<pair<int, int> > lst[maxn];

void dfs(int v){
	color[v] = 1;
	tin[v] = euler.size();
	euler.push_back(v);
	for (int u : s[v]){
		if (color[u] == 0){
			dfs(u);
			euler.push_back(v);
		}
	}
}

int sparse[18][2 * maxn], power[2 * maxn];

void build(){
	int n = euler.size();
	int k = 0;
	while ((1 << k) < n)
		k++;
	for (int i = 0; i < n; i++)
		sparse[0][i] = euler[i];
	for (int i = 0; i < k - 1; i++){
		for (int j = 0; j < n; j++){
			sparse[i + 1][j] = sparse[i][j];
			if ((1 << i) + j < n && tin[sparse[i][j]] > tin[sparse[i][j + (1 << i)]])
				sparse[i + 1][j] = sparse[i][j + (1 << i)];
		}
	}
	for (int i = 2; i < n + 1; i++){
		power[i] = power[i - 1];
		if (!((i - 1) & i))
			power[i]++;
	}
}

int getLCA(int v, int u){
	if (tin[v] > tin[u])
		swap(v, u);
	int k = power[tin[u] - tin[v] + 1];
	int p1 = sparse[k][tin[v]];
	int p2 = sparse[k][tin[u] - (1 << k) + 1];
	return tin[p1] < tin[p2] ? p1 : p2;
}

pair<int, int> q[maxn];
ll summa[maxn];
vector<pair<int, int> > query[maxn];
vector<pair<int, ll> > edges[maxn];
ll answer[maxn];

void getAns(int v){
	color[v] = 1;
	for (auto x : query[v]){
		int prev = x.first, ind = x.second;
		answer[ind] += summa[v] - summa[prev];
		int c = q[ind].first, l = q[ind].second;
		if (edges[c].size() > 0)
			answer[ind] -= edges[c].back().second;
		pair<int, ll> p = {tin[prev], -1};
		int pos = lower_bound(edges[c].begin(), edges[c].end(), p) - edges[c].begin();
		// cout << pos << endl;
		if (pos > 0)
			answer[ind] += edges[c][pos - 1].second;
		answer[ind] += l * (edges[c].size() - pos);
		// cout << answer[ind] << endl;
	}
	for (int i = 0; i < s[v].size(); i++){
		int u = s[v][i];
		if (color[u] == 0){
			int c = lst[v][i].first, l = lst[v][i].second;
			if (edges[c].size() > 0)
				edges[c].push_back({tin[v], l + edges[c].back().second});
			else
				edges[c].push_back({tin[v], l});
			summa[u] = summa[v] + l;
			getAns(u);
			edges[c].pop_back();
		}
	}
}

int main(){
    srand(17);
    ios_base::sync_with_stdio(0);
    int n, qu;
    cin >> n >> qu;
    for (int i = 1; i < n; i++){
    	int a, b, c, l;
    	cin >> a >> b >> c >> l;
    	s[a - 1].push_back(b - 1);
    	lst[a - 1].push_back({c, l});
    	s[b - 1].push_back(a - 1);
    	lst[b - 1].push_back({c, l});
    }
    dfs(0);
    build();
    for (int i = 0; i < qu; i++){
    	int c, l, a, b;
    	cin >> c >> l >> a >> b;
    	int p = getLCA(a - 1, b - 1);
    	// cout << p << endl;
    	query[a - 1].push_back({p, i});
    	query[b - 1].push_back({p, i});
    	q[i] = {c, l};
    }
    fill(color, color + n, 0);
    summa[0] = 0;
    getAns(0);
    for (int i = 0; i < qu; i++)
    	cout << answer[i] << " ";
    cout << endl;
    return 0;
}


Measured memory_bytes: 48504