#include<bits/stdc++.h>
using namespace std;

const int N = 1e5 + 10;
const int L = 20;
const int M = 4e6 + 10;

struct Edge{
    int to, color, dist;
    Edge(){}
    Edge(int to, int color, int dist):to(to),color(color),dist(dist){}
};
vector<Edge> V[N];

int n, Q, dep[N], fa[N][L];
int node_cnt, tree[N], dp[N];

struct TreeNode{
    int sum, cnt, lson, rson;
}node[M];

int build(int L, int R){
    int root = ++node_cnt;
    node[root].sum = node[root].cnt = 0;

    if(L < R){
        int mid = L + R >> 1;
        node[root].lson = build(L, mid);
        node[root].rson = build(mid+1, R);
    }

    return root;
}

int add(int root0, int p, int v){
    int root = ++node_cnt;
    int ret = root;

    node[root].cnt = node[root0].cnt + 1;
    node[root].sum = node[root0].sum + v;

    int L = 1, R = n, mid;

    while(L < R){
        mid = L + R >> 1;
        if(p <= mid){
            node[root].lson = ++node_cnt;
            node[root].rson = node[root0].rson;

            root = node[root].lson;
            root0 = node[root0].lson;
            R = mid;
        } else {
            node[root].lson = node[root0].lson;
            node[root].rson = ++node_cnt;

            root = node[root].rson;
            root0 = node[root0].rson;
            L = mid + 1;
        }

        node[root].cnt = node[root0].cnt + 1;
        node[root].sum = node[root0].sum + v;
    }

    return ret;
}

void dfs(int x){
    for(int i=0; i<V[x].size(); i++){
        int j = V[x][i].to;
        if(j == fa[x][0])   continue;

        fa[j][0] = x;
        dep[j] = dep[x] + 1;
        dp[j] = dp[x] + V[x][i].dist;
        tree[j] = add(tree[x], V[x][i].color, V[x][i].dist);

        dfs(j);
    }
}

void init(){
    node_cnt = 0;

    dep[1] = 0;
    fa[1][0] = -1;
    dp[1] = 0;
    tree[1] = build(1, n);

    dfs(1);

    for(int j=1; j<L; j++){
        for(int i=1; i<=n; i++){
            if(fa[i][j-1] == -1){
                fa[i][j] = -1;
            } else {
                fa[i][j] = fa[fa[i][j-1]][j-1];
            }
        }
    }
}

void query(int x, int f, int p, int &sum, int &cnt){
    int L = 1, R = n, mid;
    int root = tree[x];

    while(L < R){
        mid = L + R >> 1;
        if(p <= mid){
            root = node[root].lson;
            R = mid;
        } else {
            root = node[root].rson;
            L = mid + 1;
        }
    }

    sum = sum + f * node[root].sum;
    cnt = cnt + f * node[root].cnt;
}

int lca(int u, int v){
    if(dep[u] > dep[v]) swap(u, v);
    for(int i=L-1; i>=0; i--){
        if(dep[v] - dep[u] >> i & 1){
            v = fa[v][i];
        }
    }
    if(u == v)  return u;
    for(int i=L-1; i>=0; i--){
        if(fa[u][i] != fa[v][i]){
            u = fa[u][i];
            v = fa[v][i];
        }
    }
    return fa[u][0];
}

int solve(int x, int y, int c, int d){
    int u = lca(x, y);
    int ret = dp[x] + dp[y] - dp[u] * 2;

    int sum=0, cnt=0;

    query(x, 1, c, sum, cnt);
    query(y, 1, c, sum, cnt);
    query(u, -2, c, sum, cnt);

    return ret - sum + cnt * d;
}

int main(){
    int x, y, c, d;
    scanf("%d %d", &n, &Q);
    for(int i=1; i<n; i++){
        scanf("%d %d %d %d", &x, &y, &c, &d);
        V[x].push_back(Edge(y, c, d));
        V[y].push_back(Edge(x, c, d));
    }

    init();

    while(Q--){
        scanf("%d %d %d %d", &c, &d, &x, &y);
        printf("%d\n", solve(x, y, c, d));
    }

    return 0;
}


Measured memory_bytes: 55936