#include <iostream>
#include <vector>
#include <cmath>
#include <algorithm>
#include <climits>
#include <set>
#include <map>
#include <queue>
#include <deque>
#include <stack>
#include <string>

using namespace std;
using pii=pair<int,int>;
using ll=long long;

struct QUERY{
    int idx;
    int flag;
    int color;
    int len;
};

vector<int> answer;
vector<vector<QUERY>> query;

class LCA{
    public:
    struct EDGE{
        int dst;
        int color;
        int len;
    };
    vector<vector<EDGE>> adj;
    vector<vector<int>> parent;
    vector<int> lv;
    vector<int> dist;
    map<int,pii> nowcolor;
    int n;

    LCA(int n){
        parent.resize(n,vector<int>((int)ceil(log2(n)),-1));
        adj.resize(n);
        dist.resize(n);
        lv.resize(n);
        this->n=n;
    }

    void addedge(int u, int v, int c, int l)
    {
        adj[u].push_back({v,c,l});
        adj[v].push_back({u,c,l});
    }

    void dfs(int now, int p)
    {
        for(EDGE nxt : adj[now]){
            if(nxt.dst==p) continue;
            dist[nxt.dst]=dist[now]+nxt.len;
            lv[nxt.dst]=lv[now]+1;
            parent[nxt.dst][0]=now;
            dfs(nxt.dst,now);
        }
    }

    void dfs2(int now,int p)
    {
        for(QUERY q : query[now]){
            int cnt=0;
            int len=0;
            auto ret=nowcolor.find(q.color);
            if(ret!=nowcolor.end()){
                cnt=ret->second.first;
                len=ret->second.second;
            }
            answer[q.idx]+=q.flag*(dist[now]+cnt*q.len-len);
        }
        for(EDGE e : adj[now]){
            if(e.dst==p) continue;
            auto ret=nowcolor.insert({e.color,{1,e.len}});
            if(!ret.second){
                ret.first->second.first+=1;
                ret.first->second.second+=e.len;
            }
            dfs2(e.dst,now);
            ret.first->second.first-=1;
            ret.first->second.second-=e.len;
            if(ret.first->second.first==0) nowcolor.erase(ret.first);
        }
    }
    
    void makeparent()
    {
        for(int i=1; i<parent[0].size(); i++){
            for(int j=0; j<n; j++){
                if(parent[j][i-1]==-1) continue;
                parent[j][i]=parent[parent[j][i-1]][i-1];
            }
        }
    }

    int lca(int u, int v)
    {
        for(int i=parent[0].size()-1; i>=0; i--){
            if(lv[u]-(1<<i)>=lv[v]) u=parent[u][i];
            if(lv[v]-(1<<i)>=lv[u]) v=parent[v][i];
        }
        if(u!=v){
            for(int i=parent[0].size()-1; i>=0; i--){
                if(parent[u][i]!=parent[v][i]){
                    u=parent[u][i];
                    v=parent[v][i];
                }
            }
            return parent[u][0];
        }
        return u;
    }
};

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    
    int n,q;
    cin>>n>>q;
    LCA lca=LCA(n);
    for(int i=0; i<n-1; i++){
        int a,b,c,d;
        cin>>a>>b>>c>>d;
        a-=1;
        b-=1;
        lca.addedge(a,b,c,d);
    }
    lca.dfs(0,-1);
    lca.makeparent();

    answer.resize(q);
    query.resize(n);

    for(int i=0; i<q; i++){
        int x,y,u,v;
        cin>>x>>y>>u>>v;
        u-=1;
        v-=1;
        query[u].push_back({i,1,x,y});
        query[v].push_back({i,1,x,y});
        query[lca.lca(u,v)].push_back({i,-2,x,y});
    }
    lca.dfs2(0,-1);

    for(int ans : answer) cout<<ans<<"\n";
    
    return 0;
}


Measured memory_bytes: 33140