#include<bits/stdc++.h>
using namespace std;
 
#define ALL(a)  (a).begin(),(a).end()
#define ALLR(a)  (a).rbegin(),(a).rend()
#define spa << " " <<
#define lfs <<fixed<<setprecision(10)<<
#define test cout<<"test"<<endl;
#define fi first
#define se second
#define MP make_pair
#define PB push_back
#define EB emplace_back
#define rep(i,n,m) for(ll i = n; i < (ll)(m); i++)
#define rrep(i,n,m) for(ll i = n - 1; i >= (ll)(m); i--)
typedef long long ll;
typedef long double ld;
const ll MOD = 1e9+7;
//const ll MOD = 998244353;
const ll INF = 1e18;
using P = pair<ll, ll>;
template<typename T>
void chmin(T &a,T b){if(a>b)a=b;}
template<typename T>
void chmax(T &a,T b){if(a<b)a=b;}
void pmod(ll &a,ll b){a=(a+b)%MOD;}
void pmod(ll &a,ll b,ll c){a=(b+c)%MOD;}
void qmod(ll &a,ll b){a=(a*b)%MOD;}
void qmod(ll &a,ll b,ll c){a=(b*c)%MOD;}
ll median(ll a,ll b, ll c){return a+b+c-max({a,b,c})-min({a,b,c});}
void ans1(bool x){if(x) cout<<"Yes"<<endl;else cout<<"No"<<endl;}
void ans2(bool x){if(x) cout<<"YES"<<endl;else cout<<"NO"<<endl;}
void ans3(bool x){if(x) cout<<"Yay!"<<endl;else cout<<":("<<endl;}
template<typename T1,typename T2>
void ans(bool x,T1 y,T2 z){if(x)cout<<y<<endl;else cout<<z<<endl;}  
template<typename T>
void debug(vector<vector<T>>v,ll h,ll w){for(ll i=0;i<h;i++)
{cout<<v[i][0];for(ll j=1;j<w;j++)cout spa v[i][j];cout<<endl;}};
void debug(vector<string>v,ll h,ll w){for(ll i=0;i<h;i++)
{for(ll j=0;j<w;j++)cout<<v[i][j];cout<<endl;}};
template<typename T>
void debug(vector<T>v,ll n){cout<<v[0];
for(ll i=1;i<n;i++)cout spa v[i];cout<<endl;};
template<typename T>
vector<vector<T>>vec(ll x, ll y, T w){
  vector<vector<T>>v(x,vector<T>(y,w));return v;}
ll gcd(ll x,ll y){ll r;while(y!=0&&(r=x%y)!=0){x=y;y=r;}return y==0?x:y;}
template<typename T>
void emp(map<T,ll>&m, T x){m.emplace(x,0).first->second++;}
vector<ll>dx={1,0,-1,0,1,1,-1,-1};
vector<ll>dy={0,1,0,-1,1,-1,1,-1};
 
struct edge {
  ll to,cost,color;
  edge(ll x,ll y,ll z):to(x),color(y),cost(z){};
  edge():to(0LL),cost(0LL),color(0LL){};
}; 
struct LCA{
  ll datasize = 21;
  ll n,root;//rootを根とする頂点数nの根付き木
  vector<ll>depth,dist;//0から
  vector<vector<struct edge>>G;
  vector<vector<ll>>data;
  LCA(vector<vector<struct edge>>g,ll r):G(g),n(g.size()),root(r){
    data.assign(n,vector<ll>(datasize,-1));
    depth.assign(n,-1LL);
    dist.assign(n,-1LL);
    build();
  }
  void build(){
    dfs(root,0,0);
    for(ll i=1;i<datasize;i++){
      for(ll j=0;j<n;j++){
        if(data[j][i-1]==-1)data[j][i]=-1;
        else data[j][i]=data[data[j][i-1]][i-1];
      }
    }
  }
  void dfs(ll k,ll d,ll x){
    depth[k]=d;
    dist[k]=x;
    for(ll i=0;i<G[k].size();i++){
      if(depth[G[k][i].to]==-1){
        data[G[k][i].to][0]=k;
        dfs(G[k][i].to,d+1,x+G[k][i].cost);
      }
    }
  }
  ll deep(ll x){
    return x>=0?depth[x]:-1;
  }
  ll query(ll x,ll y){
    if(depth[x]<depth[y])swap(x,y);
    ll tmp = datasize - 1;
    while(depth[x]!=depth[y]){
      while(tmp>=1&&depth[y]>=deep(data[x][tmp]))tmp--;
      x = data[x][tmp];
    }
    tmp = datasize - 1;
    while(x!=y){
      while(tmp>=1&&data[x][tmp]==data[y][tmp])tmp--;
      x = data[x][tmp];
      y = data[y][tmp];
    }
    return x;
  }
};
 
//辺のオイラーツアー
struct Eulertour{
  ll n,m;
  ll root=0;
  vector<ll>vertex;//頂点列
  vector<pair<edge,ll>>data;//辺情報
  vector<ll>depth;//0から
  vector<vector<edge>>G;
  vector<pair<ll,ll>>index;//<最左index,最右index>
  Eulertour(vector<vector<edge>>g):G(g),n(g.size()){
    depth.assign(n,-1);
    index.assign(n,make_pair(10*n,10*n));
    dfs(root,0);
    m=vertex.size();
  }
  void dfs(ll k,ll d){
    depth[k]=d;
    for(ll i=0;i<G[k].size();i++){
      if(depth[G[k][i].to]==-1){
        chmin(index[k].fi,(ll)vertex.size());
        index[k].se = (ll)vertex.size();
        vertex.push_back(k);
        data.push_back(make_pair(G[k][i],1));
 
        dfs(G[k][i].to,d+1);
 
        chmin(index[G[k][i].to].fi,(ll)vertex.size());
        index[G[k][i].to].se = (ll)vertex.size();
        vertex.push_back(G[k][i].to);
        data.push_back(make_pair(G[k][i],-1));
      }
    }
    if(k==root){
      chmin(index[root].fi,(ll)vertex.size());
      index[root].se = (ll)vertex.size();
      vertex.push_back(root);
      data.push_back(MP(edge(),0));
    }
  }
  ll deep(ll x){return depth[x];}
  vector<ll>output(){//辺のコスト列を返す
    vector<ll>ret(m);
    for(ll i=0;i<m;i++){
      ret[i]=data[i].fi.cost*data[i].se;
    } 
    return ret;
  }
};  
 
template<typename T>
struct BIT{
  ll n;
  ll k=1;
  vector<T>data;
  BIT(ll size):n(size){
    data.assign(n,0);
    while(k*2<=n)k*=2;
  }
  void add(ll a,T w){
    for(ll i=a+1;i<=n;i+=i&-i)data[i-1]+=w;
  }
  T sum(ll a){
    T ret = 0;
    for(ll i=a+1;i>0;i-=i&-i)ret+=data[i-1];
    return ret;
  }
  T sum(ll a,ll b){return a>b?0:sum(b)-sum(a-1);}
  ll lower_bound(ll x){
    ll ret=0;    
    for(ll i=k;i>0;i/=2){
      if(ret+i<=n&&data[ret+i-1]<x){
        x-=data[ret+i-1];
        ret+=i;
      }
    }
    return ret;
  }
};
 
int main(){
  cin.tie(NULL);
  ios_base::sync_with_stdio(false);
  ll res=0,res1=INF,res2=-INF,buf=0;
  bool judge = true;
  ll n,q;cin>>n>>q;
  vector<vector<struct edge>>g(n);
  for(ll i=0;i<n-1;i++){
    ll a,b,c,d;
    cin>>a>>b>>c>>d;
    g[a-1].emplace_back(b-1,c,d);
    g[b-1].emplace_back(a-1,c,d);
  }
  vector<vector<P>>c(n),cy(n);
  rep(i,0,q){
    ll x,y,u,v;cin>>x>>y>>u>>v;
    c[x].emplace_back(u-1,v-1);
    cy[x].EB(y,i);
  }
  Eulertour et(g);
  LCA lca(g,0);
  BIT<ll> bit1(et.m),bit2(et.m);
  vector<ll>idx(et.m);
  vector<vector<ll>>cidx(n);
  rep(i,0,et.m){
    cidx[et.data[i].fi.color].PB(i);
  }
  rep(i,0,n){
    idx[i]=et.index[i].fi;
  }
  vector<ll>ret(q);
  rep(i,0,n){
    if(c[i].size()!=0){
      rep(j,0,cidx[i].size()){
        ll x=cidx[i][j];
        bit1.add(x,et.data[x].fi.cost*et.data[x].se);
        bit2.add(x,et.data[x].se);
      }
      rep(j,0,c[i].size()){
        ll x=c[i][j].fi,y=c[i][j].se;
        ll k=lca.query(x,y);
        ret[cy[i][j].se]=lca.dist[x]+lca.dist[y]-
          lca.dist[k]*2-bit1.sum(idx[k],idx[x]-1)-bit1.sum(idx[k],idx[y]-1)
          +cy[i][j].fi*(bit2.sum(idx[k],idx[x]-1)+bit2.sum(idx[k],idx[y]-1));
      }
      rep(j,0,cidx[i].size()){
        ll x=cidx[i][j];
        bit1.add(x,et.data[x].fi.cost*et.data[x].se*(-1));
        bit2.add(x,et.data[x].se*(-1));
      }
    }
  }
  rep(i,0,q)cout<<ret[i]<<endl;
  return 0;
}

Measured memory_bytes: 84872