#include<bits/stdc++.h>
using namespace std;
const int maxn = 3e5 + 10;
typedef long long ll;
struct node {
    int s, e, c, w, next;
}edge[maxn];
int head[maxn], len;
int n, q;
void init() {
    memset(head, -1, sizeof(head));
    len = 0;
}
void add(int s, int e, int c, int w) {
    edge[len].s = s;edge[len].e = e;
    edge[len].w = w;edge[len].c = c;
    edge[len].next = head[s];
    head[s] = len++;
}
int son[maxn], top[maxn], tid[maxn], fat[maxn], siz[maxn], dep[maxn], rak[maxn];
int dfx;
void dfs1(int x, int fa, int d) {
    siz[x] = 1, son[x] = -1, fat[x] = fa, dep[x] = d;
    for (int i = head[x]; i != -1; i = edge[i].next) {
        int y = edge[i].e;
        if (y == fa)
            continue;
        dfs1(y, x, d + 1);
        siz[x] += siz[y];
        if (son[x] == -1 || siz[y] > siz[son[x]])
            son[x] = y;
    }
}
void dfs2(int x, int c) {
    top[x] = c; tid[x] = ++dfx; rak[dfx] = x;
    if (son[x] == -1)
        return;
    dfs2(son[x], c);
    for (int i = head[x]; i != -1; i = edge[i].next) {
        int y = edge[i].e;
        if (y == fat[x] || y == son[x])
            continue;
        dfs2(y, y);
    }
}
int cnt, root[maxn], ls[maxn * 40], rs[maxn * 40], num[maxn * 40], val[maxn * 40];
struct C {
    int color, dis;
}a[maxn];
void build(C k, int l, int r, int& i) {
    num[++cnt] = num[i] + 1, val[cnt] = val[i] + k.dis, ls[cnt] = ls[i], rs[cnt] = rs[i];
    i = cnt;
    if (l == r)
        return;
    int mid = l + r >> 1;
    if (k.color <= mid)
        build(k, l, mid, ls[i]);
    else
        build(k, mid + 1, r, rs[i]);
}
C query(int u, int v, int k, int l, int r) {
    if (l == r)
        return { num[v] - num[u],val[v] - val[u] };
    int mid = l + r >> 1;
    if (k <= mid)
        return query(ls[u], ls[v], k, l, mid);
    else
        return query(rs[u], rs[v], k, mid + 1, r);
}
int solve(int cr, int dis, int x, int y) {
    C ans = { 0,0 };
    int sum = 0;
    while (top[x] != top[y]) {
        if (dep[top[x]] < dep[top[y]])
            swap(x, y);
        C t = query(root[tid[top[x]] - 1], root[tid[x]], cr, 1, n);
        sum += val[root[tid[x]]] - val[root[tid[top[x]] - 1]];
        ans.color += t.color, ans.dis += t.dis;
        x = fat[top[x]];
    }

    if (x != y) {
        if (dep[x] < dep[y])
            swap(x, y);
        C t = query(root[tid[son[y]] - 1], root[tid[x]], cr, 1, n);
        sum += val[root[tid[x]]] - val[root[tid[son[y]] - 1]];
        ans.color += t.color, ans.dis += t.dis;
    }
    return sum - ans.dis + ans.color * dis;
}
int main() {
    scanf("%d%d", &n, &q);
    init();
    for (int i = 1, x, y, c, d; i < n; i++) {
        scanf("%d%d%d%d", &x, &y, &c, &d);
        add(x, y, c, d);
        add(y, x, c, d);
    }
    dfs1(1, 0, 1);
    dfs2(1, 1);
    for (int i = 0; i < len; i += 2) {
        int x = edge[i].e;
        int y = edge[i].s;
        if (dep[x] < dep[y])
            swap(x, y);
        a[tid[x]] = { edge[i].c, edge[i].w };
    }
    for (int i = 2; i <= dfx; i++) {
        root[i] = root[i - 1];
        build(a[i], 1, n, root[i]);
    }
    while (q--) {
        int x, y, u, v;
        scanf("%d%d%d%d", &x, &y, &u, &v);
        printf("%d\n", solve(x, y, u, v));
    }
}

Measured memory_bytes: 59520