#include <bits/stdc++.h>
using namespace std;

struct Benri { Benri() { std::cin.tie(0); ios::sync_with_stdio(false); cout << fixed << setprecision(12);}} benri;

using ll = long long;
using vi = vector<int>;
using vvi = vector<vi>;
using pii = pair<int, int>;
using vll = vector<long long>;
using pll = pair<ll, ll>;
using ull = unsigned long long;

template <typename T> using PQ = priority_queue<T>;
template <typename T> using minPQ = priority_queue<T, vector<T>, greater<T>>;

#define rep(i, n) for (int i = 0; i < (int)(n); i++)
#define all(x) (x).begin(),(x).end()
#define pb push_back
#define mp make_pair
#define F first
#define S second

template<class T>bool chmax(T &a, const T &b) { if (a < b) { a = b; return 1; } return 0; }
template<class T>bool chmin(T &a, const T &b) { if (b < a) { a = b; return 1; } return 0; }

constexpr long long MOD = 1000000007;
constexpr long long MOD2 = 998244353;
constexpr double EPS = 1e-10;
constexpr int INF = 1001001001;
constexpr ll LINF = 1001001001001001001ll;



/*構造体のLCA
LCA lcaで宣言
lca.initialize(V,Graph)で初期化　ただしGraphは隣接リスト形式
lca.calc_lca(u,v)でlcaを返す
lca.calc_dist(u,v)で辺の長さが全て1のときの距離が帰ってくる
*/
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;
    }
};

struct hen {
    int to , color , cost;
    hen(int a, int b, int c): to(a), color(b), cost(c) {}
};


int N;
vector<hen> edges[100000];
vector<int> edges2[100000];  // LCA用、頂点情報だけ

vector<int> need[100000];  // need[i]: 頂点iについて値が必要になる色たち クエリ先読み
map<int, int> res_num[100000], res_sum[100000];  // res_num[i][c]: 頂点iから根までの色cの辺の本数。res_sumはその長さ合計

int dist[100000];  // 根からの距離
int now_num[100000], now_sum[100000];  // now_num[c]: 今見ている頂点から根までの色cの辺の本数。now_sumはその長さ合計

//dfs(0,1)で根から決定していく
void dfs(int i, int p) {
    for (int c : need[i]) {
        res_num[i][c] = now_num[c];
        res_sum[i][c] = now_sum[c];
    }

    for (auto& e : edges[i]) {
        int j = e.to, c = e.color, d = e.cost;
        if (j == p) continue;

        dist[j] = dist[i] + d;
        now_num[c]++;
        now_sum[c] += d;
        dfs(j, i);
        now_num[c]--;   //ちゃんと帰りがけのときに戻そうね
        now_sum[c] -= d;
    }
}

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(hen(b, c, d));
        edges[b].push_back(hen(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]);
    }

    dfs(0, -1);

    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;
        cout << ans << endl;
    }
    
}



Measured memory_bytes: 64952