#include <bits/stdc++.h>
using i64 = long long;

struct Edge {
    int to, c, d;
    Edge(int to, int c, int d) : to(to), c(c), d(d) {}
};

constexpr int size = 1 << 18;
i64 dat[size * 2 - 1];

auto query(int a, int b, int k, int l, int r) {
    if (r <= a || b <= l) return 0ll;
    if (a <= l && r <= b) return dat[k];
    return query(a, b, k * 2 + 1, l, (l + r) / 2) + query(a, b, k * 2 + 2, (l + r) / 2, r);
}

void update(int i, i64 x) {
    i += size - 1;
    dat[i] = x;
    while (i) {
        i = (i - 1) / 2;
        dat[i] = dat[i * 2 + 1] + dat[i * 2 + 2];
    }
}

auto dig(int k) {
    if (k >= size - 1) return dat[k];
    return dat[k] = dig(k * 2 + 1) + dig(k * 2 + 2);
}

void build(const std::deque<i64> &v) {
    memset(dat, 0, sizeof(dat));
    for (int i = 0; i < v.size(); i++) {
        dat[i + size - 1] = v[i];
    }
    dig(0);
}

std::vector<std::deque<Edge>> g;
std::vector<std::deque<std::pair<int, int>>> ce;
std::deque<i64> euler_tour;
std::vector<int> estart, depth;

int par[100010][17];

void dfs(int v, int p, int c, int j) {
    estart[v] = euler_tour.size() - 1;
    for (auto &e : g[v]) {
        if (e.to == p) continue;
        ce[e.c].emplace_back(euler_tour.size(), e.d);
        euler_tour.push_back(e.d);
        depth[e.to] = depth[v] + 1;
        par[e.to][0] = v;
        dfs(e.to, v, e.c, e.d);
    }
    ce[c].emplace_back(euler_tour.size(), -j);
    euler_tour.push_back(-j);
}

int main() {
    int n, q;
    std::cin >> n >> q;
    g.resize(n); ce.resize(n); estart.resize(n, -1); depth.resize(n, -1);
    for (int i = 1; i < n; i++) {
        int u, v, c, d;
        std::cin >> u >> v >> c >> d;
        --u; --v;
        g[u].emplace_back(v, c, d);
        g[v].emplace_back(u, c, d);
    }

    for (int i = 0; i < n; i++) for (int j = 0; j < 17; j++) par[i][j] = -1;
    euler_tour.emplace_back(0);
    dfs(0, -1, 0, 0);
    build(euler_tour);

    for (int i = 0; i + 1 < 17; i++) for (int j = 0; j < n; j++) {
        if (par[j][i] < 0) continue;
        par[j][i + 1] = par[par[j][i]][i];
    }


    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;
    auto sgn = [](auto t) { return t > 0 ? 1 : -1; };

    std::vector<int> ret(q);
    for (int i = 1; i < n; i++) {
        for (auto &che : ce[i]) {
            update(che.first, sgn(che.second) * pp);
        }
        for (auto &qq : cq[i]) {
            auto u = std::get<1>(qq), v = std::get<2>(qq);

            if (depth[u] > depth[v]) std::swap(u, v);
            auto diff = depth[v] - depth[u];
            for (int i = 16; i >= 0; i--) {
                if (diff & (1 << i)) v = par[v][i];
            }

            int l = -1, r = n;
            while (r - l > 1) {
                auto k = (l + r) / 2;
                int a = u, b = v;
                bool flg = a == b;
                for (int i = 16; !flg && i >= 0; i--) {
                    if ((k & (1 << i)) == 0) continue;
                    a = par[a][i];
                    b = par[b][i];
                    if (a == b) flg = true;
                }
                if (flg) r = k;
                else l = k;
            }

            int lca = v;
            for (int i = 16; i >= 0; i--) {
                if (r & (1 << i)) lca = par[lca][i];
            }

            auto d1 = query(estart[lca] + 1, estart[std::get<1>(qq)] + 1, 0, 0, size),
                d2 = query(estart[lca] + 1, estart[std::get<2>(qq)] + 1, 0, 0, size);
            auto dd = d1 % pp + d2 % pp + (d1 / pp + d2 / pp) * std::get<0>(qq);
            ret[std::get<3>(qq)] = dd;
        }
        for (auto &che : ce[i]) {
            update(che.first, che.second);
        }
    }

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

    return 0;
}


Measured memory_bytes: 224512