//#include <bits/stdc++.h>
#include "bits/stdc++.h"
using namespace std;
typedef long long ll;
//#include "boost/multiprecision/cpp_int.hpp"
//typedef boost::multiprecision::cpp_int LL;
typedef long double dd;
#define i_7 (ll)(1E9+7)
//#define i_7 998244353
#define i_5 i_7-2

ll mod(ll a){
    ll c=a%i_7;
    if(c>=0)return c;
    return c+i_7;
}
typedef pair<ll,ll> l_l;
typedef pair<dd,dd> d_d;
ll inf=(ll)1E16;
#define rep(i,l,r) for(ll i=l;i<=r;i++)
#define pb push_back
ll max(ll a,ll b){if(a<b)return b;else return a;}
ll min(ll a,ll b){if(a>b)return b;else return a;}
void Max(ll &pos,ll val){pos=max(pos,val);}//Max(dp[n],dp[n-1]);
void Min(ll &pos,ll val){pos=min(pos,val);}
void Add(ll &pos,ll val){pos=mod(pos+val);}
dd EPS=1E-9;
#define fastio ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
#define fi first
#define se second
#define endl "\n"
#define SORT(v) sort(v.begin(),v.end())
#define ERASE(v) v.erase(unique(v.begin(),v.end()),v.end())
#define POSL(v,x) (lower_bound(v.begin(),v.end(),x)-v.begin())
#define POSU(v,x) (upper_bound(v.begin(),v.end(),x)-v.begin())
//template<class T>void max(T a,T b){if(a<b)return b;else return a;}
//template<class T>void min(T a,T b){if(a>b)return b;else return a;}
//template<class T>bool Max(T&a, T b){if(a < b){a = b;return 1;}return 0;}
//template<class T>bool Min(T&a, T b){if(a > b){a = b;return 1;}return 0;}

//////////////////////////


#define N 200005
#define MAX_LOGV 30
vector<int>G[N];
int root;//根ノード
int parent[MAX_LOGV][N];//親を2^k回辿って到達する頂点(根を通り過ぎる場合は-1)
int depth[N];
void dfs(int v,int p,int d){
    parent[0][v]=p;
    depth[v]=d;
    for(auto x:G[v]){
        if(x!=p)dfs(x,v,d+1);
    }
}
void init(int V){
    //parent[0]とdepthを初期化
    dfs(root,-1,0);
    //parentを初期化
    rep(k,0,MAX_LOGV-2){
        rep(v,0,V-1){
            if(parent[k][v]<0)parent[k+1][v]=-1;
            else parent[k+1][v]=parent[k][parent[k][v]];
        }
    }
}
//uとvのLCAを求める
int lca(int u,int v){
    //uとvの深さが同じになるまで親をたどる
    if(depth[u]>depth[v])swap(u,v);
    rep(k,0,MAX_LOGV-2){
        if((depth[v]-depth[u])>>k&1){
            v=parent[k][v];
        }
    }
    if(u==v)return u;
    for(int k=MAX_LOGV-1;k>=0;k--){
        if(parent[k][u]!=parent[k][v]){
            u=parent[k][u];
            v=parent[k][v];
        }
    }
    return parent[0][u];
}
ll n,q;
struct edge{
    ll to,col,we;
};
vector<edge>v[N];
struct query{
    ll x,y,u,v,lca;
    ll ans=0;
};
vector<query>que;
vector<ll>quenum[N];
map<ll,l_l>mp;
ll sumd=0;
void dfs(ll id,ll par){
    for(auto x:quenum[id]){
        ll col=que[x].x;
        ll res=sumd-mp[col].se+mp[col].fi*que[x].y;
        
        if(id==que[x].lca){
            que[x].ans-=2*res;
            que[x].lca=-inf;
        }else{
            que[x].ans+=res;
        }
    }
    for(auto xx:v[id]){
        ll x=xx.to;
        if(x==par)continue;
        sumd+=xx.we;
        mp[xx.col].fi+=1;
        mp[xx.col].se+=xx.we;
        dfs(x,id);
        sumd-=xx.we;
        mp[xx.col].fi-=1;
        mp[xx.col].se-=xx.we;
    }
}

int main(){fastio
    cin>>n>>q;
    root=1;
    rep(i,1,n-1){
        ll a,b,c,d;cin>>a>>b>>c>>d;
        v[a].pb({b,c,d});
        v[b].pb({a,c,d});
        G[a].pb(b);
        G[b].pb(a);
    }
    init(n+1);
    rep(i,0,q-1){
        query a;
        cin>>a.x>>a.y>>a.u>>a.v;
        a.lca=lca(a.u,a.v);
        quenum[a.u].pb(i);
        quenum[a.v].pb(i);
        quenum[a.lca].pb(i);
        que.pb(a);
    }
    dfs(1,-1);
    rep(i,0,q-1){
        cout<<que[i].ans<<endl;
    }
    
    return 0;
}

/*
 5 4
 1 2 1 10
 1 3 2 20
 2 4 4 30
 5 2 1 40
 3 100000000 2 5
 1 1000 2 5
 4 1000 4 5
 3 1000 4 5
 */


Measured memory_bytes: 72828