#include <iostream>
#include <algorithm>
#include <vector>
#include <cstring>

using namespace std;

const int LGN = 17;

struct edge {
    int y, c, d;
};
struct query {
    int x, y, u, v, i;
};
typedef vector<edge> ve;

bool cq(query a, query b) {
    return a.x < b.x;
}

void dfs1(ve e[], int x, int p, int &id, int m1[]) {
    id++;
    m1[x] = id;

    for (edge y : e[x]) {
        if (y.y != p) {
            dfs1(e, y.y, x, id, m1);
        }
    }
}

void dfs2(ve e[], int x, int p[][LGN], int dis[], int h[], int sz[]) {
    for (int i = 1; i < LGN; i++) {
        p[x][i] = p[x][i-1] == -1 ? -1 : p[p[x][i-1]][i-1];
    }

    sz[x] = 1;
    for (edge y : e[x]) {
        if (y.y != p[x][0]) {
            p[y.y][0] = x;
            dis[y.y] = dis[x] + y.d;
            h[y.y] = h[x] + 1;
            dfs2(e, y.y, p, dis, h, sz);
            sz[x] += sz[y.y];
        }
    }
}

void dfs3(ve e[], int x, int p, ve ec[]) {
    for (edge y : e[x]) {
        if (y.y != p) {
            ec[y.c].push_back(y);
            dfs3(e, y.y, x, ec);
        }
    }
}

int lca(int p[][LGN], int h[], int x, int y) {
    if (h[x] < h[y]) {
        swap(x, y);
    }
    for (int i = LGN - 1; i >= 0; i--) {
        if (h[x] - (1 << i) >= h[y]) {
            x = p[x][i];
        }
    }

    if (x == y) {
        return x;
    }

    for (int i = LGN - 1; i >= 0; i--) {
        if (p[x][i] != p[y][i]) {
            x = p[x][i];
            y = p[y][i];
        }
    }

    return p[x][0];
}

void add(int bit[], int n, int x, int a) {
    for (; x <= n; x += (x & -x)) {
        bit[x] += a;
    }
}

int qry(int bit[], int x) {
    int ret = 0;
    for (; x; x -= (x & -x)) {
        ret += bit[x];
    }
    return ret;
}

int main() {
    int n, q;
    cin >> n >> q;
    ve e[n];
    for (int i = 0; i < n - 1; i++) {
        int a, b, c, d;
        cin >> a >> b >> c >> d;
        a--, b--, c--;
        e[a].push_back({b, c, d});
        e[b].push_back({a, c, d});
    }

    int m1[n];
    int id = 0;
    dfs1(e, 0, -1, id, m1);

    int p[n][LGN];
    p[0][0] = -1;
    int dis[n];
    dis[0] = 0;
    int h[n];
    h[0] = 0;
    int sz[n];
    dfs2(e, 0, p, dis, h, sz);

    ve ec[n-1];
    dfs3(e, 0, -1, ec);

    int bit1[n+1], bit2[n+1];
    memset(bit1, 0, sizeof(bit1));
    memset(bit2, 0, sizeof(bit2));

    query qu[q];
    for (int i = 0; i < q; i++) {
        cin >> qu[i].x >> qu[i].y >> qu[i].u >> qu[i].v;
        qu[i].x--, qu[i].u--, qu[i].v--;
        qu[i].i = i;
    }
    sort(qu, qu+q, cq);

    int ans[q];
    for (int i = 0; i < q; i++) {
        if (i == 0 || qu[i].x != qu[i-1].x) {
            if (i > 0) {
                for (edge a : ec[qu[i-1].x]) {
                    add(bit1, n, m1[a.y], a.d);
                    add(bit1, n, m1[a.y] + sz[a.y], -a.d);
                    add(bit2, n, m1[a.y], -1);
                    add(bit2, n, m1[a.y] + sz[a.y], 1);
                }
            }
            for (edge a : ec[qu[i].x]) {
                add(bit1, n, m1[a.y], -a.d);
                add(bit1, n, m1[a.y] + sz[a.y], a.d);
                add(bit2, n, m1[a.y], 1);
                add(bit2, n, m1[a.y] + sz[a.y], -1);
            }
        }

        int disu = dis[qu[i].u] + qry(bit1, m1[qu[i].u]) + qry(bit2, m1[qu[i].u]) * qu[i].y;
        int disv = dis[qu[i].v] + qry(bit1, m1[qu[i].v]) + qry(bit2, m1[qu[i].v]) * qu[i].y;
        int lcauv = lca(p, h, qu[i].u, qu[i].v);
        int dislca = dis[lcauv] + qry(bit1, m1[lcauv]) + qry(bit2, m1[lcauv]) * qu[i].y;
        ans[qu[i].i] = disu + disv - 2 * dislca;
    }

    for (int i = 0; i < q; i++) {
        cout << ans[i] << endl;
    }

    return 0;
}


Measured memory_bytes: 24376