#define _USE_MATH_DEFINES
#include "bits/stdc++.h"
using namespace std;
#define FOR(i,j,k) for(int (i)=(j);(i)<(int)(k);++(i))
#define rep(i,j) FOR(i,0,j)
#define each(x,y) for(auto &(x):(y))
#define mp make_pair
#define MT make_tuple
#define all(x) (x).begin(),(x).end()
#define debug(x) cout<<#x<<": "<<(x)<<endl
#define smax(x,y) (x)=max((x),(y))
#define smin(x,y) (x)=min((x),(y))
#define MEM(x,y) memset((x),(y),sizeof (x))
#define sz(x) (int)(x).size()
#define RT return
using ll = long long;
using pii = pair<int, int>;
using vi = vector<int>;
using vll = vector<ll>;

class HLDecomposition {
    int cur = 0;
    void bfs(const vector<vector<int> > &G) {
        queue<tuple<int, int, int> > que;
        vector<int> order;
        que.push(make_tuple(0, -1, 0));
        while (!que.empty()) {
            int u, pre, d;
            tie(u, pre, d) = que.front();
            que.pop();
            parent[u] = pre;
            depth[u] = d;
            order.push_back(u);
            for (int v : G[u])if (v != pre) {
                que.push(make_tuple(v, u, d + 1));
            }
        }
        reverse(order.begin(), order.end());
        for (int u : order) {
            sub[u] = 1;
            for (int v : G[u])if (v != parent[u])sub[u] += sub[v];
        }
    }

    void dfs_stk(const vector<vector<int> > & G) {
        stack<pair<int, int> > stk;
        stk.push(make_pair(0, 0));
        while (!stk.empty()) {
            int u, h, pre;
            tie(u, h) = stk.top();
            stk.pop();
            head[u] = h;
            id[u] = cur++;
            pre = parent[u];
            int heavy = -1, maxi = 0;
            for (int v : G[u]) {
                if (v != pre && maxi < sub[v]) {
                    maxi = sub[v];
                    heavy = v;
                }
            }
            for (int v : G[u]) {
                if (v != pre&&v != heavy) {
                    stk.push(make_pair(v, v));
                }
            }
            if (heavy != -1)stk.push(make_pair(heavy, h));
        }
    }
public:
    vector<int> parent, depth, sub, id, head;

    HLDecomposition(const vector<vector<int> > &G) {
        parent = depth = sub = id = head = vector<int>(G.size());
        bfs(G);
        dfs_stk(G);
    }

    /*
    パス(u, v)で通る頂点を半開区間の集合に変換する。
    O(log(|V|))
    */
    vector<pair<int, int> > goUpToLCA(int u, int v) {
        vector<pair<int, int> > res;
        while (true) {
            if (head[u] == head[v]) {
                if (depth[u] > depth[v])swap(u, v);
                res.emplace_back(id[u], id[v] + 1);
                break;
            } else {
                if (depth[head[u]] > depth[head[v]])swap(u, v);
                res.emplace_back(id[head[v]], id[v] + 1);
                v = parent[head[v]];
            }
        }
        reverse(res.begin(), res.end());
        return res;
    }

    int getLCA(int u, int v) {
        while (true) {
            if (head[u] == head[v]) {
                if (depth[u] > depth[v])swap(u, v);
                break;
            } else {
                if (depth[head[u]] > depth[head[v]])swap(u, v);
                v = parent[head[v]];
            }
        }
        return u;
    }
};

template<class Val>
struct BinaryIndexedTree {
    int n;
    vector<Val> t;
    BinaryIndexedTree() {}
    BinaryIndexedTree(int _n) :n(_n + 1), t(_n + 1) {}
    void add(int k, Val val) {
        k++;
        while (k < n) {
            t[k] += val;
            k += (k&-k);
        }
    }
    void set(int k, Val val) {
        add(k, -sum(k, k + 1));
        add(k, val);
    }
    Val sum(int k) {
        Val r = 0;
        while (k > 0) {
            r += t[k];
            k -= (k&-k);
        }
        return r;
    }
    Val sum(int l, int r) {
        return sum(r) - sum(l);
    }
};
typedef BinaryIndexedTree<int> BIT;



void solve() {
    int N, Q;
    cin >> N >> Q;

    vector<vi> G(N);

    // col, dist
    map<pii, pii> edges;
    rep(i, N - 1) {
        int a, b, c, d;
        cin >> a >> b >> c >> d;
        --a; --b; --c;
        G[a].push_back(b);
        G[b].push_back(a);
        edges[mp(a, b)] = mp(c, d);
        edges[mp(b, a)] = mp(c, d);
    }

    vector<vector<pii>> dif(N);
    BIT ori(N);
    HLDecomposition hld(G);
    rep(i, N) {
        int j = hld.parent[i];
        pii e = edges[mp(i, j)];
        if (j != -1) {
            ori.add(hld.id[i], e.second);
            dif[e.first].emplace_back(hld.id[i], e.second);
        }
    }

    // y, u, v, id;
    using T = tuple<int, int, int, int>;
    vector<vector<T>> qrs(N);
    rep(i, Q) {
        int x, y, u, v;
        cin >> x >> y >> u >> v;
        --x; --u; --v;
        qrs[x].emplace_back(y, u, v, i);
    }

    vi ans(Q);
    BIT cnt(N), sum(N);
    rep(i, N) {
        if (sz(qrs[i]) == 0)continue;

        each(p, dif[i]) {
            cnt.add(p.first, 1);
            sum.add(p.first, p.second);
        }
        
        each(q, qrs[i]) {
            int y, u, v, k;
            tie(y, u, v, k) = q;
            auto path = hld.goUpToLCA(u, v);
            int lca = hld.getLCA(u, v);

            int &res = ans[k];
            each(p, path) {
                if (p.first == hld.id[lca]) {
                    p.first++;
                }
                res += ori.sum(p.first, p.second);
                res -= sum.sum(p.first, p.second);
                res += cnt.sum(p.first, p.second)*y;
            }
        }

        each(p, dif[i]) {
            cnt.add(p.first, -1);
            sum.add(p.first, -p.second);
        }
    }

    each(res, ans)cout << res << endl;
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout << fixed << setprecision(15);
    solve();
    return 0;
}


Measured memory_bytes: 31816