#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<b;i++)
#define rrep(i,a,b) for(int i=a;i>=b;i--)
#define fore(i,a) for(auto &i:a)
#define all(x) (x).begin(),(x).end()
//#pragma GCC optimize ("-O3")
using namespace std; void _main(); int main() { cin.tie(0); ios::sync_with_stdio(false); _main(); }
typedef long long ll; const int inf = INT_MAX / 2; const ll infl = 1LL << 60;
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; }
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
struct Edge {
    int src, dst;
    int color;
    int weight;
    Edge() : src(0), dst(0), color(0), weight(0) {}
    Edge(int s, int d, int c, int w) : src(s), dst(d), color(c), weight(w) {}
};
using Edges = std::vector<Edge>;
using Graph = std::vector<Edges>;

class lca {
public:
    const int n = 0;
    const int log2_n = 0;
    std::vector<std::vector<int>> parent;
    std::vector<int> depth;
    vector<int> distance;

    lca() {}

    lca(const Graph &g, int root)
        : n(g.size()), log2_n(log2(n) + 1), parent(log2_n, std::vector<int>(n)), depth(n), distance(n) {
        dfs(g, root, -1, 0, 0);
        for (int k = 0; k + 1 < log2_n; k++) {
            for (int v = 0; v < (int)g.size(); v++) {
                if (parent[k][v] < 0)
                    parent[k + 1][v] = -1;
                else
                    parent[k + 1][v] = parent[k][parent[k][v]];
            }
        }
    }

    void dfs(const Graph &g, int v, int p, int d, int d2) {
        parent[0][v] = p;
        depth[v] = d;
        distance[v] = d2;
        for (auto &e : g[v]) {
            if (e.dst != p) dfs(g, e.dst, v, d + 1, d2 + e.weight);
        }
    }

    int get(int u, int v) {
        if (depth[u] > depth[v]) std::swap(u, v);
        for (int k = 0; k < log2_n; k++) {
            if ((depth[v] - depth[u]) >> k & 1) {
                v = parent[k][v];
            }
        }
        if (u == v) return u;
        for (int k = log2_n - 1; k >= 0; k--) {
            if (parent[k][u] != parent[k][v]) {
                u = parent[k][u];
                v = parent[k][v];
            }
        }
        return parent[0][u];
    }

    int length(int u, int v)
    {
        return depth[u] + depth[v] - depth[get(u, v)] * 2;
    }

    int dist(int u, int v)
    {
        return distance[u] + distance[v] - distance[get(u, v)] * 2;
    }
};

struct Query
{
    int color, id, coeff, y;
    Query(int color, int id, int coeff, int y) : color(color), id(id), coeff(coeff), y(y) {}
};

vector<Query> qs[100005];

int cnt[100005];
ll sum[100005];

vector<ll> ans;

void dfs(const Graph& g, int v, int p = -1)
{
    for (const auto& q : qs[v])
    {
        ll x = -sum[q.color];
        x += static_cast<ll>(q.y) * cnt[q.color];
        ans[q.id] += x * q.coeff;
    }

    for (const auto& e : g[v])
    {
        if (e.dst == p) continue;
        ++cnt[e.color]; sum[e.color] += e.weight;
        dfs(g, e.dst, v);
        --cnt[e.color]; sum[e.color] -= e.weight;
    }
}

void _main()
{
    int N, Q;
    cin >> N >> Q;
    Graph g(N);
    rep(i, 0, N - 1)
    {
        int a, b, c, d;
        cin >> a >> b >> c >> d;
        --a; --b;
        g[a].emplace_back(a, b, c, d);
        g[b].emplace_back(b, a, c, d);
    }
    lca LCA(g, 0);
    ans.resize(Q);
    rep(i, 0, Q)
    {
        int x, y, a, b;
        cin >> x >> y >> a >> b;
        --a; --b;
        const int c = LCA.get(a, b);
        ans[i] = LCA.dist(a, b);
        qs[a].emplace_back(x, i, 1, y);
        qs[b].emplace_back(x, i, 1, y);
        qs[c].emplace_back(x, i, -2, y);
    }
    dfs(g, 0);
    rep(i, 0, Q)
    {
        cout << ans[i] << endl;
    }
}


Measured memory_bytes: 30580