#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define F first
#define S second
#define pii pair<int, int>
#define eb emplace_back
#define all(v) v.begin(), v.end()
#define rep(i, n) for (int i = 0; i < (n); ++i)
#define rep3(i, l, n) for (int i = l; i < (n); ++i)
#define sz(v) (int)v.size()
const int inf = 1e9 + 7;
const ll INF = 1e18;
const int mod = 1000000007;
#define abs(x) (x >= 0 ? x : -(x))
#define lb(v, x) (int)(lower_bound(all(v), x) - v.begin())
#define ub(v, x) (int)(upper_bound(all(v), x) - v.begin())
template<typename T1, typename T2> inline bool chmin(T1 &a, T2 b) { if (a > b) { a = b; return 1; } return 0; }
template<typename T1, typename T2> inline bool chmax(T1 &a, T2 b) { if (a < b) { a = b; return 1; } return 0; }
template<typename T> T gcd(T a, T b) { if (b == 0) return a; return gcd(b, a % b); }
template<typename T> T lcm(T a, T b) { return a / gcd(a, b) * b; }
template<typename T> T pow(T a, int b) { return b ? pow(a * a, b / 2) * (b % 2 ? a : 1) : 1; }
ll modpow(ll a, int b, int _mod) { return b ? modpow(a * a % _mod, b / 2, _mod) * (b % 2 ? a : 1) % _mod : 1; }
template<class T> ostream& operator << (ostream& os, const vector<T>& vec) { for (auto &vi: vec) os << vi << " "; return os; }
template<class T, class U> ostream& operator << (ostream& os, const pair<T, U>& p) { os << p.F << " " << p.S; return os; }
template<typename T >inline istream& operator >> (istream& is, vector<T>& v) { rep(j, sz(v)) is >> v[j]; return is; }
template<class T> inline void add(T &a, int b) { a += b; if (a >= mod) a -= mod; }



void solve();

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    cout << fixed << setprecision(10);
    
    int T;
    // cin >> T;
    T = 1;
    
    while (T--) {
        solve();
    }
}


const int MAX_LOG_V = 25;
vector<vector<int> > G;
// v の 2^i 個上の祖先
vector<vector<int> > parent;
vector<int> depth;
int root;

// n を定義した直後に呼んで
void init_size(int n) {
    G.resize(n);
    // v の 2^i 個上の祖先
    parent = vector<vector<int> >(MAX_LOG_V, vector<int>(n));
    depth.resize(n);
}
// 親と, 根からの深さを初期化
void dfs(int v, int p, int d) {
    parent[0][v] = p;
    depth[v] = d;
    for (int nv : G[v]) {
        if (nv == p) continue;
        dfs(nv, v, d + 1);
    }
}

// G を作った後呼んで
void init(int n) {
    rep(i, n) if (sz(G[i]) == 1) root = i;
    
    // 親と, 根からの深さを初期化
    dfs(root, -1, 0);
    
    // for k, v 順番命
    rep(k, MAX_LOG_V - 1) {
        rep(v, n) {
            if (parent[k][v] < 0) parent[k + 1][v] = -1;
            else parent[k + 1][v] = parent[k][parent[k][v]];
        }
    }
}

// 頂点 lca を返す
int lca(int u, int v) {
    // まずは深さを合わせる
    if (depth[u] > depth[v]) swap(u, v);
    for (int k = 0; k + 1 < MAX_LOG_V; ++k) {
        if ((depth[v] - depth[u]) >> k & 1) {
            v = parent[k][v];
        }
    }
    if (u == v) return u;
    // u, v を上げていく
    for (int k = MAX_LOG_V - 1; k >= 0; k--) {
        if (parent[k][u] != parent[k][v]) {
            u = parent[k][u];
            v = parent[k][v];
        }
    }
    return parent[0][u];
}

// 答え
// dr[u] : 根から u の距離 dist - 根から u のその色の合計 sum + 根から u の辺の数 num * d
// dr[u] + dr[v] - 2 * dr[l]

// https://atcoder.jp/contests/abc133/submissions/6301894

vector<vector<int> > colors;
const int maxn = 100005;
// vector<vector<map<int, int> > > できない? sum[x][y]
map<int, int> sum[maxn], num[maxn]; // 頂点, 色, value
vector<vector<tuple<int, int, int> > > G2;

vector<int> sum2, num2, dist;

void dfs2(int v, int p) {
    for (int c : colors[v]) {
        sum[v][c] = sum2[c];
        num[v][c] = num2[c];
    }
    
    for (auto e : G2[v]) {
        int nv, c, d;
        tie(nv, c, d) = e;
        if (nv == p) continue;
        
        sum2[c] += d;
        num2[c]++;
        dist[nv] = dist[v] + d;
        dfs2(nv, v);
        sum2[c] -= d;
        num2[c]--;
    }
}

void solve() {
    int n, q;
    cin >> n >> q;
    
    init_size(n);
    G2.resize(n);
    
    rep(i, n - 1) {
        int a, b;
        cin >> a >> b;
        a--; b--;
        G[a].eb(b);
        G[b].eb(a);
        
        int c, d; // color, dist
        cin >> c >> d;
        c--;
        
        G2[a].eb(b, c, d);
        G2[b].eb(a, c, d);
    }
    
    init(n);
    // cout << depth << endl;
    colors.resize(n);
    
    vector<tuple<int, int, int, int, int> > Q(q);
    rep(i, q) {
        // color c を dist d に変えたときの dist(u, v)
        int c, d, u, v;
        cin >> c >> d >> u >> v;
        c--; u--; v--;
        int l = lca(u, v);
        Q[i] = make_tuple(c, d, u, v, l);
        
        colors[u].eb(c);
        colors[v].eb(c);
        colors[l].eb(c);
    }
    
    sum2.resize(n);
    num2.resize(n);
    dist.resize(n);
    dfs2(root, -1);
    
    rep(i, q) {
        int c, d, u, v, l;
        tie(c, d, u, v, l) = Q[i];
        auto dr = [&](int v) {
            // cout << dist[v] << " " << sum[v][c] << " " << num[v][c] << " " << d << endl;
            return dist[v] - sum[v][c] + num[v][c] * d;
        };
        cout << dr(u) + dr(v) - 2 * dr(l) << endl;
    }
}



Measured memory_bytes: 68088