/*
勉強させて頂きました。ありがとうございます。
I learn with this link.
https://betrue12.hateblo.jp/entry/2019/07/08/000306
https://atcoder.jp/contests/abc133/submissions/6301894
 */

#include <bits/stdc++.h>
#include <map>
#include <set>
#include <vector>
#include <algorithm>
#include <iostream>

#include <bitset>
#include <cassert>
#include <queue>
#include <random>
#include <stack>
#include <iomanip>

using namespace std;

#define rep(i, n) for (ll i = 0; i < (ll)n; i++)
#define repf(i, a, b) for (ll i = (ll)a; i < (ll)b; i++)
#define repr(i, a, b) for (ll i = (ll)a; i > (ll)b; i--)

#define repv(x, arr) for (auto &x : arr)
#define all(v) (v).begin(), (v).end()
#define vec(name, num) vector<ll> name((num), 0);
#define mp(a, b) make_pair(a, b)
#define op(i) cout << (i) << endl;
#define F first
#define S second

typedef long long ll;
typedef long double ld;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef pair<ld, ld> pdd;
typedef vector<ll> vll;
typedef vector<vll> vvll;

const ll mod = 1e9 + 7;
const int infi = 2147483647;
const ll infl = 1e17;

struct LCA{
    static const int BITLEN_MAX = 30;
    //最大2＾30までの深さを考える
    vector<int> parent[BITLEN_MAX];
    //それぞれの頂点の2^k前の親を表す
    vector<int> depth;
    //深さ

    //LCAの持つ情報。親と深さの情報から任意の頂点対でのLCAがlogNで求められる

    int bitlen;
    //logNの切り上げた値

    void initialize(int N,const vector<int> edges[]){
        //edgesをポインタ渡ししている。
        int root = 0;
        bitlen = 1;
        while ((1<<bitlen)<N)
            bitlen++;
        for (int i = 0; i < bitlen;i++)
            parent[i].resize(N);
        //parentの各配列を頂点数で初期化
        depth.resize(N, -1);

        dfs(root, -1, 0, edges);
        //深さと1つ前の親を求めるDFS
        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;
                    //もし2＾k個前が根よりも前のとき、再帰的に代入するとindex outになるため直接-1をいれる
                }
                else{
                    parent[k + 1][v] = parent[k][parent[k][v]];
                    //vから2＾k前の頂点の2＾k前の頂点＝2＾(k+1)前の頂点
                }
            }
        }
    }
    void dfs(int v,int p,int d,const vector<int> edges[]){
        //いまの頂点v、1つ前の頂点p、いまの深さd、枝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);
        //vのほうが深いようにしておくと便利
        for (int k = 0; k < bitlen; k++){
            if ( ((depth[v]-depth[u])>>k)&1)
                v = parent[k][v];        }
            //もしbitが立っていれば、その分戻る
        if (u==v)
            return u;
        //uがvの祖先ならuを返す
        for (int k = bitlen - 1; k >= 0;k--){
            if (parent[k][u]!=parent[k][v]){
                u = parent[k][u];
                v = parent[k][v];
                //2＾k戻って違うなら戻っておく
                //大きい方から調べないとダメ(それはそう)
            }
        }
        //いまの頂点は違うが、1、2，4…個戻ると同じ事は保証されているので1つ戻るところがLCAである
        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;
        //LCAを使って重みなしの距離を求める
    }
};

int N;
vector<vector<int>> edges[100000];
//各頂点から出る枝の、先、色、重みのベクトルを持つ
//3次元配列
vector<int> edges2[100000];
//各頂点から出る枝の頂点だけを持つ。LCAの計算では頂点対がわかればよいので別で保持する

vector<int> need[100000];
//各頂点で必要となる色。二次元配列
map<int, int> res_num[100000], res_sum[100000];
//各頂点で色：根から頂点の間の、その色の辺の数　と　色：根から頂点の間のその色の辺の重みの和　を表す

int dist[100000];
//距離ベクトル
int now_sum[100000], now_num[100000];
//現在の各色の辺の数と重みの和

void dfs(int i,int p){
    for (int c:need[i]){
        res_sum[i][c] = now_sum[c];
        res_num[i][c] = now_num[c];
        //現在の頂点で必要な情報を記録する。needには頂点iで必要な色が全て入っている。
    }
    
    for(auto& e:edges[i]){
        int j = e[0], c = e[1], d = e[2];
        //全枝に対して
        if (j==p)
            continue;
        //直前の頂点なら調べない(ループ阻止)
        dist[j] = dist[i] + d;
        //普通のdfsと同じく距離を記録
        now_num[c]++;
        now_sum[c] += d;
        //現在の色の合計と数を更新
        dfs(j, i);
        //深いところを探索。いま調べたところをキャンセル引数にいれておく
        now_num[c]--;
        now_sum[c] -= d;
        //この関数が終わるとき1つ上に戻って別の枝から調べるため、現在の色の値を戻しておく
    }
}

int main(){
    int 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--;
        edges[a].push_back({b, c, d});
        edges[b].push_back({a, c, d});
        edges2[a].push_back(b);
        edges2[b].push_back(a);
    }
    
    LCA lca;
    lca.initialize(N, edges2);

    int X[100000], Y[100000], U[100000], V[100000], L[100000];
    for (int i = 0; i < Q;i++){
        cin >> X[i] >> Y[i] >> U[i] >> V[i];
        X[i]--;
        U[i]--;
        V[i]--;
        L[i] = lca.calc_lca(U[i], V[i]);
        need[U[i]].push_back(X[i]);
        need[V[i]].push_back(X[i]);
        need[L[i]].push_back(X[i]);
        //クエリのu,vと、そのLCAであるlで色xについての情報が求められるという記録
    }

    dfs(0, -1);
    //全頂点に対して必要な情報をDFSで調べる

    for (int i = 0; i < Q;i++){
        int x = X[i], y = Y[i], u = U[i], v = V[i], l = L[i];

        int du = dist[u] - res_sum[u][x] + res_num[u][x] * y;
        int dv = dist[v] - res_sum[v][x] + res_num[v][x] * y;
        int dl = dist[l] - res_sum[l][x] + res_num[l][x] * y;
        int ans = du + dv - 2 * dl;
        //du：根からuまでで、色xの辺を距離yに変更したときの距離
        //du+dv-2dl：lcaを使って計算
        cout << ans << endl;
    }
    return 0;
}

Measured memory_bytes: 73268