#include <bits/stdc++.h>
using i64 = std::int64_t;

struct HLDecomposition {
    using Graph = std::vector<std::deque<int>>;
    int size;
    Graph g;
    std::vector<int> par, depth, chs, heavy, decomposed, inv, head;

    void dfs(int root) {
        std::deque<std::pair<int, unsigned>> q { { root, 0 } };
        par[root] = -1;
        depth[root] = 0;

        while (!q.empty()) {
            auto &v = q.back();
            if (v.second < g[v.first].size()) {
                auto ch = g[v.first][v.second++];
                if (ch == par[v.first]) continue;
                par[ch] = v.first;
                depth[ch] = depth[v.first] + 1;
                q.emplace_back(ch, 0);
            } else {
                int h = -1;
                for (auto ch : g[v.first]) {
                    if (ch == par[v.first]) continue;
                    chs[v.first] += chs[ch];
                    if (h < 0 || chs[h] < chs[ch]) h = ch;
                }
                if (h >= 0) heavy[v.first] = h;
                q.pop_back();
            }
        }
    }

    void bfs(int root) {
        static int next = 0;
        std::deque<int> q { root };

        while (!q.empty()) {
            int v = q.front();
            q.pop_front();
            for (int i = v; i >= 0; i = heavy[i]) {
                decomposed[i] = next;
                inv[next++] = i;
                head[i] = v;
                for (int ot : g[i]) {
                    if (ot == par[i] || ot == heavy[i]) continue;
                    q.push_back(ot);
                }
            }
        }
    }

    HLDecomposition() = delete;
    HLDecomposition(int size)
        : size(size)
        , g(size)
        , par(size)
        , depth(size)
        , chs(size, 1)
        , heavy(size, -1)
        , decomposed(size)
        , inv(size)
        , head(size) {}
    HLDecomposition(const Graph &gr)
        : size(gr.size())
        , g(gr)
        , par(size)
        , depth(size)
        , chs(size, 1)
        , heavy(size, -1)
        , decomposed(size)
        , inv(size)
        , head(size) {}
    HLDecomposition(Graph &&gr)
        : size(gr.size())
        , g(gr)
        , par(size)
        , depth(size)
        , chs(size, 1)
        , heavy(size, -1)
        , decomposed(size)
        , inv(size)
        , head(size) {}

    void add_edge(unsigned u, unsigned v) {
        g[u].push_back(v);
        g[v].push_back(u);
    }

    void build(int root = 0) {
        dfs(root);
        bfs(root);
    }

    int lca(int u, int v) {
        while (head[u] != head[v]) {
            if (decomposed[u] < decomposed[v]) v = par[head[v]];
            else u = par[head[u]];
        }
        return decomposed[u] < decomposed[v] ? u : v;
    }

    template <typename F>
    void for_each(int u, int v, const F &f) {
        while(true) {
            if (decomposed[u] > decomposed[v]) std::swap(u, v);
            f(std::max(decomposed[head[v]], decomposed[u]), decomposed[v]);
            if (head[u] == head[v]) return;
            v = par[head[v]];
        }
    }

    template <typename F>
    void for_each_edge(int u, int v, const F &f) {
        while (true) {
            if (decomposed[u] > decomposed[v]) std::swap(u, v);
            if (head[u] == head[v]) {
                if (u != v) f(decomposed[u] + 1, decomposed[v]);
                return;
            }
            f(decomposed[head[v]], decomposed[v]);
            v = par[head[v]];
        }
    }
};

template <typename T, typename F>
class SegmentTree {
    int size;
    T id;
    T *dat;
    F f;

    T query_impl(const int a, const int b, const int k, const int l, const int r) const {
        if (r <= a || b <= l) return id;
        if (a <= l && r <= b) return dat[k];
        return f(query_impl(a, b, k * 2 + 1, l, (l + r) / 2),
                 query_impl(a, b, k * 2 + 2, (l + r) / 2, r));
    }

public:
    SegmentTree(const int n, const T &id, const F f) : id(id), f(f) {
        size = 2;
        while (size < n) size *= 2;
        dat = new T[2 * size - 1];
        for (int i = 0; i < 2 * size - 1; i++) dat[i] = id;
    }

    ~SegmentTree() {
        delete[] dat;
    }

    void update(int i, const T x) {
        i += size - 1;
        dat[i] = x;
        while (i > 0) {
            i = (i - 1) / 2;
            dat[i] = f(dat[i * 2 + 1], dat[i * 2 + 2]);
        }
    }

    T query(const int a, const int b) const {
        return query_impl(a, b, 0, 0, size);
    }

    T operator[](const int i) const {
        return dat[i + size - 1];
    }
};

template <typename T, typename F>
auto make_st(int n, T id, F f) {
    return SegmentTree<T, F>(n, id, f);
}

struct Edge {
    int a, b, d;
    Edge(int a, int b, int d) : a(a), b(b), d(d) {}
};

int main() {
    int n, q;
    std::cin >> n >> q;
    std::vector<std::deque<Edge>> ce(n);
    HLDecomposition hld(n);
    for (int i = 1; i < n; i++) {
        int a, b, c, d;
        std::cin >> a >> b >> c >> d;
        --a; --b;
        hld.add_edge(a, b);
        ce[c].emplace_back(a, b, d);
    }
    hld.build();

    auto st = make_st(2 * n, 0ll, [](auto a, auto b) { return a + b; });

    auto getv = [&](int a, int b) {
        return hld.decomposed[hld.depth[a] > hld.depth[b] ? a : b];
    };

    for (int i = 1; i < n; i++) {
        for (const auto &e : ce[i]) {
            st.update(getv(e.a, e.b), e.d);
        }
    }

    std::vector<std::deque<std::tuple<int, int, int, int>>> cq(n);
    for (int i = 0; i < q; i++) {
        int x, y, u, v;
        std::cin >> x >> y >> u >> v;
        cq[x].emplace_back(y, u - 1, v - 1, i);
    }

    constexpr i64 pp = 10000000000;
    i64 sum = 0;
    auto add = [&](int l, int r) {
        sum += st.query(l, r + 1);
    };
    std::vector<i64> ret(q);

    for (int i = 1; i < n; i++) {
        if (cq[i].empty()) continue;
        for (const auto &e : ce[i]) {
            st.update(getv(e.a, e.b), pp);
        }

        for (auto &qq : cq[i]) {
            hld.for_each_edge(std::get<1>(qq), std::get<2>(qq), add);
            ret[std::get<3>(qq)] = sum / pp * std::get<0>(qq) + sum % pp;
            sum = 0;
        }

        for (const auto &e : ce[i]) {
            st.update(getv(e.a, e.b), e.d);
        }
    }

    for (auto r : ret) std::cout << r << std::endl;
    return 0;
}


Measured memory_bytes: 211684