#include <bits/stdc++.h>

#define REP(i,n) for (int i=0;i<(n);++i)

using namespace std;

using pii = pair<int, int>;

struct edge {
    typedef size_t weight_type;

    size_t m_to;

    edge(size_t to) : m_to(to) { }

    inline size_t to() const { return m_to; }

    inline weight_type weight() const { return 1; }
};

template <typename Weight>
struct weighted_edge : public edge {
    using weight_type = Weight;

    weight_type m_weight;
    int color;

    weighted_edge(size_t to, weight_type weight, int color) : edge(to), m_weight(weight), color(color) { }

    inline weight_type weight() const { return m_weight; }
};

template <class Edge>
struct graph {
    using edge_type = Edge;

    const size_t m_n_vertices;
    std::vector<std::vector<edge_type>> m_edges;

    graph(size_t n_vertices) : m_n_vertices(n_vertices), m_edges(n_vertices) { }

    inline size_t n_vertices() const { return m_n_vertices; }

    inline void add_edge(size_t from, const edge_type &e) {
        m_edges[from].emplace_back(e);
    }

    inline std::vector<edge_type> edges_from(size_t v) const {
        return m_edges[v];
    }
};

class lowest_common_ancestor {

    size_t log2_N; // ciel(log2(N))
    std::vector<std::vector<size_t>> parent;
    std::vector<size_t> depth;

    size_t n_th_parent(size_t u, size_t n) {
        for (size_t i = 0; (1 << i) <= n; ++i) {
            if (n & (1 << i)) {
                u = parent[u][i];
            }
        }
        return u;
    }

public:

    // g is a tree
    template <class Graph>
    lowest_common_ancestor(const Graph &g, size_t root) {

        using Edge = typename Graph::edge_type;

        size_t N = g.n_vertices();
        size_t max_height = N - 1;
        log2_N = 32 - __builtin_clz(max_height);
        
        parent.assign(N, std::vector<size_t>(log2_N));
        depth.resize(N);

        std::function<void(int, int)> dfs = [&](int u, int p) {
            for (const Edge &e: g.edges_from(u)) {
                size_t v = e.to();
                if (v == p) {
                    continue;
                }
                parent[v][0] = u;
                depth[v] = depth[u] + 1;
                dfs(v, u);
            }
        };

        parent[root][0] = root;
        depth[root] = 0;
        dfs(root, root);

        for (size_t i = 1; i < log2_N; ++i) {
            for (size_t u = 0; u < N; ++u) {
                parent[u][i] = parent[parent[u][i - 1]][i - 1];
            }
        }
    }

    size_t query(size_t u, size_t v) {
        if (depth[u] > depth[v]) {
            u = n_th_parent(u, depth[u] - depth[v]);
        } else if (depth[v] > depth[u]) {
            v = n_th_parent(v, depth[v] - depth[u]);
        }
        if (u == v) {
            return u;
        }
        for (int i = log2_N - 1; i >= 0; --i) {
            if (parent[u][i] != parent[v][i]) {
                u = parent[u][i];
                v = parent[v][i];
            }
        }
        return parent[u][0];
    }
};

int main() {
    cin.tie(0);
    ios::sync_with_stdio(false);

    using Edge = weighted_edge<int>;
    using Graph = graph<Edge>;

    int N, Q;
    cin >> N >> Q;
    Graph g(N);
    REP(_, N - 1) {
        int a, b, c, d;
        cin >> a >> b >> c >> d;
        --a;
        --b;
        --c;
        g.add_edge(a, Edge(b, d, c));
        g.add_edge(b, Edge(a, d, c));
    }
    int root = 0;
    lowest_common_ancestor lcm(g, root);
    vector<vector<pair<int, int>>> op(N); // (query_id, sign)
    vector<int> x(Q), y(Q);
    REP(query_id, Q) {
        int u, v;
        cin >> x[query_id] >> y[query_id] >> u >> v;
        --x[query_id];
        --u;
        --v;
        int LCM = lcm.query(u, v);
        op[u].emplace_back(query_id, 1);
        op[v].emplace_back(query_id, 1);
        op[LCM].emplace_back(query_id, -1);
    }
    
    vector<int> result(Q, 0);
    vector<int> color_edge_count(N - 1);
    vector<int> color_edge_weight(N - 1);

    function<void(int, int, int)> dfs = [&](int u, int parent, int weight_sum) {
        for (const pii &queryId_sign: op[u]) {
            int query_id, sign;
            tie(query_id, sign) = queryId_sign;
            int color = x[query_id];
            int weight_after = y[query_id];
            int weight_sum_after = weight_sum - color_edge_weight[color] + color_edge_count[color] * weight_after;
            if (sign == 1) {
                result[query_id] += weight_sum_after;
            } else if (sign == -1) {
                result[query_id] -= 2 * weight_sum_after;
            }
        }
        for (const Edge &e: g.edges_from(u)) {
            int v = e.to();
            if (v == parent) continue;
            int weight = e.weight();
            int color = e.color;
            color_edge_count[color]++;
            color_edge_weight[color] += weight;
            dfs(v, u, weight_sum + weight);
            color_edge_count[color]--;
            color_edge_weight[color] -= weight;
        }
    };

    dfs(root, -1, 0);

    REP(i, Q) cout << result[i] << '\n';
    cout << flush;

    return 0;
}


Measured memory_bytes: 44152