#include <iostream>
#include <vector>
#include <set>
#include <map>

using namespace std;

class Edge {
public:
    explicit Edge(int src, int dst, int color, int len) : src(src), dst(dst), color(color), len(len) {}
    int src, dst, color, len;
};

class Query {
public:
    explicit Query(int x, int y, int u, int v) : x(x), y(y), u(u), v(v), lca(-1) {}
    int x, y, u, v, lca;
};

class Solver {
public:
    explicit Solver(int N) : parents(N), depth(N), dist(N), needs(N), info(N) {}
    void makeParents(const vector<vector<Edge>>& g){
        travel(g, 0, -1);
    }
    void readQueries(const vector<Query>& query){
        for(auto& q : query){
            int lca = getLCA(q.u, q.v);
            needs[q.u].insert(q.x);
            needs[q.v].insert(q.x);
            needs[lca].insert(q.x);
        }
    }
    void prepare(const vector<vector<Edge>>& g){
        vector<pair<int,int>> colors(g.size(), make_pair(0, 0));
        prepareImpl_(g, 0, -1, 0, colors);
    }
    void solve(const vector<Query>& query){
        for(auto& q : query){
            int lca = getLCA(q.u, q.v);
            int d = dist[q.u] + dist[q.v] - 2 * dist[lca];
            int num = info[q.u][q.x].first + info[q.v][q.x].first - 2 * info[lca][q.x].first;
            int pd = info[q.u][q.x].second + info[q.v][q.x].second - 2 * info[lca][q.x].second;
            cout << (d - pd + num * q.y) << endl;
        }
    }
private:
    void travel(const vector<vector<Edge>>& g, int pos, int prev){
        depth[pos] = (prev == -1 ? 0 : depth[prev] + 1);
        int check = prev;
        while(check != -1){
            parents[pos].push_back(check);
            if(parents[check].size() < parents[pos].size()) break;
            check = parents[check][parents[pos].size()-1];
        }
        for(auto& e : g[pos]){
            if(e.dst == prev) continue;
            travel(g, e.dst, pos);
        }
    }
    void prepareImpl_(const vector<vector<Edge>>& g, int pos, int prev, int d, vector<pair<int,int>>& colors){
        dist[pos] = d;
        for(auto t : needs[pos]){
            info[pos][t] = colors[t];
        }
        for(auto& e : g[pos]){
            if(e.dst == prev) continue;
            ++colors[e.color].first;
            colors[e.color].second += e.len;
            prepareImpl_(g, e.dst, pos, d+e.len, colors);
            --colors[e.color].first;
            colors[e.color].second -= e.len;
        }
    }
    int toParents(int pos, int step){
        for(int d=0;step;d++){
            if(step%2) pos = parents[pos][d];
            step /= 2;
        }
        return pos;
    }
    int getLCA(int a, int b){
        if(depth[a] > depth[b]) swap(a, b);
        b = toParents(b, depth[b] - depth[a]);
        if(a == b) return a;
        for(int i=parents[a].size()-1;i>=0;i--){
            if(parents[a].size() <= i) continue;
            if(parents[a][i] != parents[b][i]){
                a = parents[a][i];
                b = parents[b][i];
            }
        }
        return parents[a][0];
    }
private:
    vector<vector<int>> parents;
    vector<int> depth;
    vector<int> dist;
    vector<set<int>> needs;
    vector<map<int, pair<int, int>>> info;
};

int main(){
    int N, Q;
    while(cin >> N >> Q){
        vector<vector<Edge>> g(N);
        for(int i=0;i<N-1;i++){
            int a, b, c, d;
            cin >> a >> b >> c >> d;
            --a; --b;
            g[a].emplace_back(a, b, c, d);
            g[b].emplace_back(b, a, c, d);
        }
        vector<Query> query;
        for(int i=0;i<Q;i++){
            int x, y, u, v;
            cin >> x >> y >> u >> v;
            --u; --v;
            query.emplace_back(x, y, u, v);
        }
        Solver solver(N);
        solver.makeParents(g);
        solver.readQueries(query);
        solver.prepare(g);
        solver.solve(query);
    }
}

Measured memory_bytes: 55660