#include <bits/stdc++.h>
#define ll long long
#define BUF 1e5
#define INF 1 << 30
constexpr ll mod = 1e9 + 7;
using namespace std;
ll A, B, C, D, G, H, N, M, L, K, P, Q, R, W, X, Y, Z;
string S, T;
ll ans = 0;

class HLD {
public:
    int size, root;
    vector<int> node2id, id2node, depth, hvp_head, hvp_next, parent, sub_size;
    vector<vector<int>> tree;

    HLD() {}
    HLD(vector<vector<int>> t) : root(0), size(t.size()), node2id(size), id2node(size), depth(size), hvp_head(size), hvp_next(size), parent(size), sub_size(size, 0), tree(t) {}
    HLD(vector<vector<int>> t, int root) : root(root), size(t.size()), node2id(size), id2node(size), depth(size), hvp_head(size), hvp_next(size), parent(size), sub_size(size, 0), tree(t) {}

    void build() {
        dfs_sub_size(root, -1, 0);
        bfs_id(root);
    }

    int dfs_sub_size(int node, int p, int dep) {
        parent[node] = p;
        depth[node] = dep++;
        int n = tree[node].size();
        if (n == 1) {
            sub_size[node] = 1;
            hvp_next[node] = -1;
            return 1;
        }
        int max_child = 0;
        for (int i = 0; i < n; i++) {
            int adj = tree[node][i];
            if (adj == p)
                continue;
            int tmp = dfs_sub_size(adj, node, dep);
            if (max_child < tmp) {
                max_child = tmp, hvp_next[node] = adj;
            }
            sub_size[node] += tmp;
        }
        return ++sub_size[node];
    }

    void bfs_id(int root) {
        int id = 0;
        queue<int> q;
        q.push(root);
        while (!q.empty()) {
            int head = q.front();
            q.pop();
            for (int node = head; node != -1; node = hvp_next[node]) {
                hvp_head[node] = head;
                node2id[node] = id++;
                id2node[id] = node;
                for (auto adj : tree[node]) {
                    if (adj == hvp_next[node] || adj == parent[node])
                        continue;
                    q.push(adj);
                }
            }
        }
    }

    int lca(int u, int v) {
        while (1) {
            if (node2id[u] > node2id[v])
                swap(u, v);
            if (hvp_head[u] == hvp_head[v])
                return u;
            v = parent[hvp_head[v]];
        }
    }

    int dist(int u, int v) {
        return depth[u] + depth[v] - 2 * depth[lca(u, v)];
    }
};
struct HLDecomposition {
    int n, pos;
    vector<vector<int>> G;
    vector<int> vid, head, sub, hvy, par, dep, inv, type;

    HLDecomposition() {}
    HLDecomposition(int sz) : n(sz), pos(0), G(n),
                              vid(n, -1), head(n), sub(n, 1), hvy(n, -1),
                              par(n), dep(n), inv(n), type(n) {}

    void add_edge(int u, int v) {
        G[u].push_back(v);
        G[v].push_back(u);
    }

    void build(vector<int> rs = vector<int>(1, 0)) {
        int c = 0;
        for (int r : rs) {
            dfs(r);
            bfs(r, c++);
        }
    }

    void dfs(int rt) {
        using T = pair<int, int>;
        stack<T> st;
        par[rt] = -1;
        dep[rt] = 0;
        st.emplace(rt, 0);
        while (!st.empty()) {
            int v = st.top().first;
            int &i = st.top().second;
            if (i < (int)G[v].size()) {
                int u = G[v][i++];
                if (u == par[v])
                    continue;
                par[u] = v;
                dep[u] = dep[v] + 1;
                st.emplace(u, 0);
            } else {
                st.pop();
                int res = 0;
                for (int u : G[v]) {
                    if (u == par[v])
                        continue;
                    sub[v] += sub[u];
                    if (res < sub[u])
                        res = sub[u], hvy[v] = u;
                }
            }
        }
    }

    void bfs(int r, int c) {
        int &k = pos;
        queue<int> q({r});
        while (!q.empty()) {
            int h = q.front();
            q.pop();
            for (int i = h; i != -1; i = hvy[i]) {
                type[i] = c;
                vid[i] = k++;
                inv[vid[i]] = i;
                head[i] = h;
                for (int j : G[i])
                    if (j != par[i] && j != hvy[i])
                        q.push(j);
            }
        }
    }

    // for_each(vertex)
    // [l,r] <- attention!!
    void for_each(int u, int v, const function<void(int, int)> &f) {
        while (1) {
            if (vid[u] > vid[v])
                swap(u, v);
            f(max(vid[head[v]], vid[u]), vid[v]);
            if (head[u] != head[v])
                v = par[head[v]];
            else
                break;
        }
    }

    // for_each(edge)
    // [l,r] <- attention!!
    void for_each_edge(int u, int v, const function<void(int, int)> &f) {
        while (1) {
            if (vid[u] > vid[v])
                swap(u, v);
            if (head[u] != head[v]) {
                f(vid[head[v]], vid[v]);
                v = par[head[v]];
            } else {
                if (u != v)
                    f(vid[u] + 1, vid[v]);
                break;
            }
        }
    }

    int lca(int u, int v) {
        while (1) {
            if (vid[u] > vid[v])
                swap(u, v);
            if (head[u] == head[v])
                return u;
            v = par[head[v]];
        }
    }

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

map<pair<int, int>, pair<int, int>> edge;

void dfs(HLDecomposition &hld, int node, map<int, pair<int, int>> &cmp, map<int, map<int, pair<int, int>>> &nmp, vector<int> &dist) {
    int p = hld.par[node];
    for (auto &cd : nmp[node]) {
        cd.second = cmp[cd.first];
    }
    for (auto adj : hld.G[node]) {
        if (adj == p)
            continue;
        int c = edge[{node, adj}].first;
        int d = edge[{node, adj}].second;
        cmp[c].first++;
        cmp[c].second += d;
        dist[adj] = dist[node] + d;
        dfs(hld, adj, cmp, nmp, dist);
        cmp[c].first--;
        cmp[c].second -= d;
    }
}

int main() {
    cin >> N >> Q;
    vector<vector<int>> tree(N);
    vector<int> dist(N, 0);
    HLDecomposition hld(N);
    for (int i = 0; i < N - 1; i++) {
        int a, b, c, d;
        cin >> a >> b >> c >> d;
        a--, b--, c--;
        tree[a].push_back(b);
        tree[b].push_back(a);
        hld.add_edge(a, b);
        edge[{a, b}] = {c, d};
        edge[{b, a}] = {c, d};
    }
    //HLD hld(tree);
    hld.build();
    map<int, map<int, pair<int, int>>> nmp;
    map<int, pair<int, int>> cmp;
    vector<pair<int, int>> queryuv(Q);
    vector<pair<int, int>> queryxy(Q);
    vector<int> vlca(Q);
    for (int q = 0; q < Q; q++) {
        int x, y, u, v;
        cin >> x >> y >> u >> v;
        x--, u--, v--;
        queryuv[q] = {u, v};
        queryxy[q] = {x, y};
        vlca[q] = hld.lca(u, v);
        nmp[vlca[q]][x] = {0, 0};
        nmp[u][x] = {0, 0};
        nmp[v][x] = {0, 0};
    }
    dfs(hld, 0, cmp, nmp, dist);
    for (int i = 0; i < Q; i++) {
        int u = queryuv[i].first;
        int v = queryuv[i].second;
        int x = queryxy[i].first;
        int y = queryxy[i].second;
        int lca = vlca[i];
        int dlca = dist[lca] - nmp[lca][x].second + nmp[lca][x].first * y;
        int du = dist[u] - nmp[u][x].second + nmp[u][x].first * y;
        int dv = dist[v] - nmp[v][x].second + nmp[v][x].first * y;
        cout << du + dv - 2 * dlca << endl;
    }
}

Measured memory_bytes: 65756