#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, 1), 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, 1), tree(t) {}

    void build() {
        dfs_sub_size(root);
        bfs_id(root);
    }

    void dfs_sub_size(int root) {
        stack<pair<int, int>> stk;
        stk.emplace(root, 0);
        parent[root] = -1;
        depth[root] = 0;
        while (!stk.empty()) {
            int now = stk.top().first;
            int &index = stk.top().second;
            int n = tree[now].size();
            int p = parent[now];
            if (index < n) {
                int adj = tree[now][index++];
                if (adj == p)
                    continue;
                stk.emplace(adj, 0);
                depth[adj] = depth[now] + 1;
                parent[adj] = now;
            } else {
                stk.pop();
                int max_child = 0;
                if(tree[now].size()==1)hvp_next[now]=-1;
                for (int adj : tree[now]) {
                    if (adj == p)
                        continue;
                    if (max_child < sub_size[adj]) {
                        max_child = sub_size[adj], hvp_next[now] = adj;
                    }
                    sub_size[now] += sub_size[adj];
                }
            }
        }
    }

    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)];
    }
};
map<pair<int, int>, pair<int, int>> edge;

void dfs(HLD &hld, int node, map<int, pair<int, int>> &cmp, map<int, map<int, pair<int, int>>> &nmp, vector<int> &dist) {
    int p = hld.parent[node];
    for (auto &cd : nmp[node]) {
        cd.second = cmp[cd.first];
    }
    for (auto adj : hld.tree[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);
    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);
        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: 65424