#include <iostream>
#include <iomanip>
#include <string>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <algorithm>
#include <numeric>
#include <cmath>
#include <cassert>

using namespace std;
typedef long long LL;
template <typename F, typename S> std::ostream& operator<<(ostream& os, const pair<F,S>& p) {
    os << "(" << p.first << "," << p.second << ")"; return os; }
template <typename T> ostream& operator<<(ostream& os, const vector<T>& v) {
    os << "["; for(const T& a: v){ os << a << ", "; } os << "]"; return os; }
template <typename K, typename V> ostream& operator<<(ostream& os, const map<K,V>& m) {
    os << "{"; for(const auto& p: m){ os << p.first <<":"<< p.second << ", "; } os << "}"; return os; }


void setNodeDepth(LL cur, LL parent, LL depth, vector<LL>& node_depth, vector<vector<tuple<LL,LL,LL>>>& edge){
    node_depth[cur] = depth;
    for(auto e: edge[cur]){
        if(get<0>(e) == parent) continue;
        setNodeDepth(get<0>(e), cur, depth+1, node_depth, edge);
    }
}

void setParent(LL cur, LL parent, LL len, vector<vector<LL>>& ancestors, vector<vector<LL>>& dist, vector<vector<tuple<LL,LL,LL>>>& edge){
    ancestors[cur][0] = parent;
    dist[cur][0] = len;
    for(auto e: edge[cur]){
        if(get<0>(e) == parent) continue;
        setParent(get<0>(e), cur, get<2>(e), ancestors, dist, edge);
    }
}

int getAncestor(LL u, LL depth, vector<LL>& node_depth, vector<vector<LL>>& ancestors){
    LL diff = node_depth[u] - depth;
    assert(diff >= 0);
    if(diff == 0) return u;
    LL cur = 0;
    while((1<<(1+cur)) <= diff) ++cur;
    return getAncestor(ancestors[u][cur], depth, node_depth, ancestors);
}

int commonAncestor(LL u, LL v, vector<LL>& node_depth, vector<vector<LL>>& ancestors){
    int left = 0;
    int right = min(node_depth[u], node_depth[v])+1;
    while(left+1 < right){
        LL middle = (left + right) / 2;
        LL a1 = getAncestor(u, middle, node_depth, ancestors);
        LL a2 = getAncestor(v, middle, node_depth, ancestors);
        if(a1 == a2){
            left = middle;
        }else{
            right = middle;
        }
    }
    return getAncestor(u, left, node_depth, ancestors);
}

LL getDist(LL u, vector<LL>& node_depth, vector<vector<LL>>& dist, vector<vector<LL>>& ancestors){
    LL depth = node_depth[u];
    if(depth == 0) return 0;
    LL cur = 0;
    while(ancestors[u][cur+1] >= 0) ++cur;
    return dist[u][cur] + getDist(ancestors[u][cur], node_depth, dist, ancestors);
}


LL getCost(LL u, LL v, vector<LL>& node_depth, vector<vector<LL>>& dist, vector<vector<LL>>& ancestors){
    LL ca = commonAncestor(u, v, node_depth, ancestors);
    LL c1 = getDist(u, node_depth, dist, ancestors);
    //cerr << "c1=" << c1 << endl;
    LL c2 = getDist(v, node_depth, dist, ancestors);
    //cerr << "c2=" << c2 << endl;
    LL c3 = getDist(ca, node_depth, dist, ancestors);
    //cerr << "c3=" << c3 << endl;
    //cerr << "c1=" << u << " " << c1 << ", c2=" << v << " " << c2 << ", c3=" << ca  << " " << c3 << ",++ " << c1 + c2 - c3*2 << endl;
    LL cost = c1 + c2 - c3*2;
    return cost;
}


int main(){
    LL n, q;
    cin >> n >> q;
    vector<vector<tuple<LL,LL,LL>>> edge(n);
    vector<vector<tuple<LL,LL,LL>>> color2edge(n-1);
    for(LL i = 0; i < n-1; ++i){
        LL a, b, c, d;
        cin >> a >> b >> c >> d;
        --a; --b; --c;
        edge[a].emplace_back(b, c, d);
        edge[b].emplace_back(a, c, d);
        color2edge[c].emplace_back(a, b, d);
    }

    vector<LL> node_depth(n);
    setNodeDepth(0, -1, 0, node_depth, edge);

    vector<vector<LL>> ancestors(n, vector<LL>(20, -1));
    vector<vector<LL>> dist(n, vector<LL>(20, 0));
    setParent(0, -1, 0, ancestors, dist, edge);

    for(LL i = 1; i < 20; ++i){
        for(LL j = 0; j < n; ++j){
            if(ancestors[j][i-1] >= 0){
                ancestors[j][i] = ancestors[ancestors[j][i-1]][i-1];
                dist[j][i] = dist[j][i-1] + dist[ancestors[j][i-1]][i-1];
            }
        }
    }

    vector<tuple<LL,LL,LL,LL, LL>> query;
    vector<LL> ans(q);
    for(LL i = 0; i < q; ++i){
        LL x, y, u, v;
        cin >> x >> y >> u >> v;
        --x; --u; --v;
        query.emplace_back(x, y, u, v, i);
    }
    sort(query.begin(), query.end());
    LL last_color = -1;
    vector<vector<LL>> dist2(n, vector<LL>(20, 0));
    vector<vector<LL>> dist_cnt(n, vector<LL>(20, 0));
    for(LL i = 0; i < q; ++i){
        LL color = get<0>(query[i]);
        LL len = get<1>(query[i]);
        LL u = get<2>(query[i]);
        LL v = get<3>(query[i]);
        LL qi = get<4>(query[i]);
        if(color2edge[color].size() >= 500){
            if(last_color != color){
                last_color = color;
                vector<vector<tuple<LL,LL,LL>>> edge2(edge.begin(), edge.end());
                vector<vector<tuple<LL,LL,LL>>> edge_cnt(edge.begin(), edge.end());
                for(LL j = 0; j < n; ++j){
                    for(auto& e: edge2[j]){
                        if(get<1>(e) != color) get<2>(e) = 0;
                    }
                    for(auto& e: edge_cnt[j]){
                        if(get<1>(e) == color){
                            get<2>(e) = 1;
                        }else{
                            get<2>(e) = 0;
                        }
                    }
                }
                dist2 = vector<vector<LL>>(n, vector<LL>(20, 0));
                setParent(0, -1, 0, ancestors, dist2, edge2);
                for(LL k = 1; k < 20; ++k){
                    for(LL j = 0; j < n; ++j){
                        if(ancestors[j][k-1] >= 0){
                            dist2[j][k] = dist2[j][k-1] + dist2[ancestors[j][k-1]][k-1];
                        }
                    }
                }
                dist_cnt = vector<vector<LL>>(n, vector<LL>(20, 0));
                setParent(0, -1, 0, ancestors, dist_cnt, edge_cnt);
                for(LL k = 1; k < 20; ++k){
                    for(LL j = 0; j < n; ++j){
                        if(ancestors[j][k-1] >= 0){
                            dist_cnt[j][k] = dist_cnt[j][k-1] + dist_cnt[ancestors[j][k-1]][k-1];
                        }
                    }
                }
            }
            LL normal_cost = getCost(u, v, node_depth, dist, ancestors);
            LL colored_cost = getCost(u, v, node_depth, dist2, ancestors);
            LL additional_cost = getCost(u, v, node_depth, dist_cnt, ancestors);
            ans[qi] = normal_cost - colored_cost + additional_cost * len;
        }else{
            LL cost = getCost(u, v, node_depth, dist, ancestors);
            LL ca = commonAncestor(u, v, node_depth, ancestors);
            for(auto t: color2edge[color]){
                LL u2 = get<0>(t);
                LL v2 = get<1>(t);
                LL d2 = get<2>(t);
                if(node_depth[v2] > node_depth[u2]) swap(u2, v2);
                if(commonAncestor(ca, u2, node_depth, ancestors) != u2){
                    if(commonAncestor(u, u2, node_depth, ancestors) == u2
                        || commonAncestor(v, u2, node_depth, ancestors) == u2){
                        //cerr << "+" << len << " -" << d2 << endl;
                        cost += len - d2;
                    }
                }
            }
            //cerr << "cost:" << cost << endl;
            ans[qi] = cost;
        }
    }
    for(LL i = 0; i < q; ++i){
        cout << ans[i] << endl;
    }
    return 0;
}



Measured memory_bytes: 140972