#include <algorithm>
#include <iostream>
#include <vector>
#include <queue>
using namespace std;
typedef long long ll;
typedef pair<int, ll> P;

template <typename T>
struct Edge
{
    int to;
    T cost;
};

template <typename T>
struct WeightedGraph
{
    int n;
    vector<vector<Edge<T>>> g;
    
    WeightedGraph(int n) : n(n){
        g.resize(n);
    }
    
    void init(int n_){
        n = n_;
        g.resize(n_);
    }
    
    void add_edge(int from, int to, T cost){
        g[from].push_back((Edge<T>){to, cost});
    }
};

template <typename T>
struct WeightedTree
{
    int n;
    int root;
    vector<vector<Edge<T>>> t;
    vector<int> par;
    vector<int> dpt;

    void init(WeightedGraph<T> &g, int root_){
        n = g.n;
        root = root_;
        t.resize(n);
        par.resize(n);
        dpt.resize(n);
        fill(dpt.begin(), dpt.end(), -1);
        queue<int> que;
        par[root] = -1;
        dpt[root] = 0;
        que.push(root);
        while(que.size()){
            int pa = que.front();
            que.pop();
            for(Edge<T> e : g.g[pa]){
                int ch = e.to;
                if(dpt[ch] == -1){
                    t[pa].push_back(e);
                    par[ch] = pa;
                    dpt[ch] = dpt[pa] + 1;
                    que.push(ch);
                }
            }
        }
    }
    
    WeightedTree(){}
    
    WeightedTree(WeightedGraph<T> &g, int root_){
        init(g, root_);
    }
};

WeightedTree<P> t;
int par[100005][20];
ll s[200005], l[200005];
int p[100005];
int k;
vector<int> col[100005];

int common(int u, int v){
    if(t.dpt[u] < t.dpt[v]) swap(u, v);
    int r = t.dpt[u] - t.dpt[v];
    for(int j = 19; j >= 0; j--) if((r >> j) & 1) u = par[u][j];
    if(u == v) return u;
    for(int j = 19; j >= 0; j--) if(par[u][j] != par[v][j]) u = par[u][j], v = par[v][j];
    return par[u][0];
}

void dfs(int i){
    if(p[i] == -1) p[i] = k;
    k++;
    for(Edge<P> e : t.t[i]){
        s[k] = s[*(col[e.cost.first].end() - 1)] + e.cost.second;
        l[k] = l[*(col[e.cost.first].end() - 1)] + 1;
        col[e.cost.first].push_back(k);
        dfs(e.to);
        s[k] = s[*(col[e.cost.first].end() - 1)] - e.cost.second;
        l[k] = l[*(col[e.cost.first].end() - 1)] - 1;
        col[e.cost.first].push_back(k);
        k++;
    }
}

vector<ll> Dijkstra(){
    int n = t.n;
    vector<ll> d(n);
    fill(d.begin(), d.end(), -1);
    queue<int> que;
    d[t.root] = 0;
    que.push(t.root);
    while(que.size()){
        int now = que.front();
        que.pop();
        for(Edge<P> e : t.t[now]){
            d[e.to] = d[now] + e.cost.second;
            que.push(e.to);
        }
    }
    return d;
}

int main()
{
    int n, q;
    cin >> n >> q;
    WeightedGraph<P> g(n);
    for(int i = 0; i < n - 1; i++){
        int a, b, c;
        ll d;
        cin >> a >> b >> c >> d;
        a--; b--; c--;
        g.add_edge(a, b, P(c, d));
        g.add_edge(b, a, P(c, d));
    }
    t.init(g, 0);
    for(int i = 0; i < n; i++) par[i][0] = t.par[i];
    for(int j = 1; j < 20; j++){
        for(int i = 0; i < n; i++){
            if(par[i][j - 1] != -1) par[i][j] = par[par[i][j - 1]][j - 1];
            else par[i][j] = -1;
        }
    }
    for(int i = 0; i < n; i++) col[i].push_back(0);
    for(int i = 0; i < n; i++) p[i] = -1;
    vector<ll> d = Dijkstra();
    dfs(0);
    for(int c = 0; c < q; c++){
        int x, u, v;
        ll y;
        cin >> x >> y >> u >> v;
        x--; u--; v--;
        int w = common(u, v);
        int lu = *(upper_bound(col[x].begin(), col[x].end(), p[u]) - 1);
        int lv = *(upper_bound(col[x].begin(), col[x].end(), p[v]) - 1);
        int lw = *(upper_bound(col[x].begin(), col[x].end(), p[w]) - 1);
        cout << (d[u] + d[v] - d[w] * 2) - (s[lu] + s[lv] - s[lw] * 2) + (l[lu] + l[lv] - l[lw] * 2) * y << endl;
    }
}


Measured memory_bytes: 38900