#include <bits/stdc++.h>
using namespace std;
typedef pair<int, int> pii;

struct edge{int to, cost, color;};

const int MAX_N = (int)1e5 + 5;
int dist[MAX_N], start[MAX_N], fin[MAX_N], cnt = 0;
vector<vector<int>> ancestor;
vector<int> depth(MAX_N);
vector<edge> G[MAX_N];
vector<pii> nums[MAX_N], colors[MAX_N];

void __output(int n, int size_r){
    for(int i=0;i<size_r;i++){
        for(int j=0;j<n;j++) cout<<ancestor[i][j]<<' ';
        cout<<endl;
    }
}

void dfs(int s, int pre, int d){
    depth[s] = d;
    ancestor[0][s] = pre;
    for(auto u : G[s]){
        if(u.to != pre){
            dfs(u.to, s, d+1);
        }
    }
}

void dfs2(int s, int p){
    for(auto u : G[s]){
        if(u.to != p){
            start[u.to] = ++cnt;
            colors[u.color].push_back({u.to, 1});
            nums[u.color].push_back({1, u.cost});
            dist[u.to] = dist[s] + u.cost;
            dfs2(u.to, s);
            fin[u.to] = ++cnt;
            colors[u.color].push_back({u.to, -1});
            nums[u.color].push_back({-1, -u.cost});
        }
    }
}

int query(int u, int x, int y){
    int left = -1, right = colors[x].size();
    while(1<right-left){
        int mid = (left+right) / 2;
        int v = colors[x][mid].first;
        if(colors[x][mid].second>0){
            if(v==-1 || start[v]<=start[u]) left = mid;
            else right = mid;
        } else {
            if(fin[v]<start[u]) left = mid;
            else right = mid;
        }
    }
    int a = nums[x][left].second, b = nums[x][left].first;
    int res = dist[u] - nums[x][left].second + y * nums[x][left].first;
    return res;
}

void CalcAncestors(int n, int root){
    // O(n log n)
    int size_r = 0;
    while((1<<size_r)<=n) {ancestor.emplace_back(vector<int>(n, -1)), size_r++;}

    dfs(root, 0, 0);
    //__output(n, size_r);

    for(int i=1;i<size_r;i++){
        for(int j=0;j<n;j++){
            int u = ancestor[i-1][j];
            int v = ancestor[i-1][u];
            ancestor[i][j] = ancestor[i-1][ancestor[i-1][j]];
        }
    }

    //__output(n, size_r);
}

int Ancestor(int x, int k){
    int res = x;
    for(int i=0;(1<<i)<=k;i++){
        if(ancestor.size()<=i) return -1;
        if((k>>i) & 1) res = ancestor[i][res];
    }
    return res;
}

int lowestCommonAncestor(int x, int y){
    if(x==y) return x;
    if(depth[x]>depth[y]) swap(x, y);
    y = Ancestor(y, depth[y]-depth[x]);
    if(x==y) return x;
    int left = 0, right = ancestor.size();
    while(1<right-left){
        int mid = (left+right) / 2;
        if(ancestor[mid][x]==ancestor[mid][y]) right = mid;
        else left = mid;
    }
    int u = ancestor[left][x], v = ancestor[left][y];
    if(u==v) return u;
    return lowestCommonAncestor(u, v);
}


int main(){
    ios::sync_with_stdio(false), cin.tie(nullptr);
    int N, Q;
    cin>>N>>Q;
    for(int i=0;i<N-1;i++){
        int a, b, c, d;
        cin>>a>>b>>c>>d;
        a--, b--;
        G[a].push_back({b, d, c});
        G[b].push_back({a, d, c});
    }
    CalcAncestors(N, 0);
    for(int i=0;i<N;i++) nums[i].push_back({0, 0}), colors[i].push_back({-1, 1});
    dfs2(0, -1);
    fin[0] = 2 * (N-1);
    for(int i=0;i<N;i++){
        for(int j=1;j<nums[i].size();j++){
            nums[i][j].first += nums[i][j-1].first;
            nums[i][j].second += nums[i][j-1].second;
        }
    }

    /*
    for(int i=0;i<N;i++){
        for(auto c : nums[i]) cout<<c.second<<' ';
        cout<<endl;
    }
     */

    for(int i=0;i<Q;i++){
        int x, y, u, v;
        cin>>x>>y>>u>>v, u--, v--;
        int anc = lowestCommonAncestor(u, v);
        //printf("%d %d %d\n", query(u, x, y),query(v, x, y),2*query(anc, x, y));
        printf("%d\n", query(u, x, y)-2*query(anc, x, y)+query(v, x, y));
    }
    return 0;
}

Measured memory_bytes: 37408