#include<bits/stdc++.h>

#define debug(x) cerr << #x << ": " << x << endl
#define debugArray(x,n) for(long long hoge = 0; (hoge) < (n); ++ (hoge)) cerr << #x << "[" << hoge << "]: " << x[hoge] << endl
using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef vector<ll> vll;
const ll INF = LLONG_MAX/2;
const ll MOD = 1e9+7;
const double EPS=1e-12;


template<typename M>
struct LinkCutTree{
private:
    using T=typename M::T;
    using E=typename M::E;
public:
    struct Node{
        Node *l,*r,*p;
        size_t sz;
        size_t idx;
        bool rev;
        T val,dat,rdat;
        E laz;
        Node():sz(1){}
        Node(size_t idx,T val,E laz):
        sz(1),idx(idx),rev(0),val(val),dat(val),rdat(val),laz(laz){l=r=p=nullptr;}
        bool is_root(){
            return !p||(p->l!=this&&p->r!=this);
        }
    };
private:
    const size_t LIM = 1e6;
    vector<Node> pool;
    size_t ptr;
    vector<Node*> nodes;
    void propagate(Node *t,E v){
        t->laz=M::h(t->laz,v);
        t->val=M::g(t->val,v,1);
        t->dat=M::g(t->dat,v,t->sz);
        t->rdat=M::g(t->rdat,v,t->sz);
    }

    void toggle(Node *t){
        swap(t->l,t->r);
        swap(t->dat,t->rdat);
        t->rev^=1;
    }

    void eval(Node *t){
        if(t->laz!=M::ei()){
            if(t->l) propagate(t->l,t->laz);
            if(t->r) propagate(t->r,t->laz);
            t->laz=M::ei();
        }
        if(t->rev){
            if(t->l) toggle(t->l);
            if(t->r) toggle(t->r);
            t->rev=false;
        }
    }

    void recalc(Node *t){
        t->sz = 1;
        t->rdat=t->dat=t->val;
        if(t->l) t->sz += t->l->sz,t->dat=M::f(t->l->dat,t->dat),t->rdat=M::f(t->rdat,t->l->rdat);
        if(t->r) t->sz += t->r->sz,t->dat=M::f(t->dat,t->r->dat),t->rdat=M::f(t->r->rdat,t->rdat);
    }

    void rotR(Node *t){
        Node *x=t->p,*y=x->p;
        if((x->l=t->r)) t->r->p=x;
        t->r=x;x->p=t;
        recalc(x);recalc(t);
        if((t->p=y)){
            if(y->l==x) y->l=t;
            if(y->r==x) y->r=t;
            recalc(y);
        }
    }

    void rotL(Node *t){
        Node *x=t->p,*y=x->p;
        if((x->r=t->l)) t->l->p=x;
        t->l=x;x->p=t;
        recalc(x);recalc(t);
        if((t->p=y)){
            if(y->l==x) y->l=t;
            if(y->r==x) y->r=t;
            recalc(y);
        }
    }

    void splay(Node *t){
        eval(t);
        while(!t->is_root()){
            Node *q=t->p;
            if(q->is_root()){
                eval(q);eval(t);
                if(q->l==t) rotR(t);
                else rotL(t);
            }else{
                auto *r=q->p;
                eval(r);eval(q);eval(t);
                if(r->l==q){
                    if(q->l==t) rotR(q),rotR(t);
                    else rotL(t),rotR(t);
                }else{
                    if(q->r==t) rotL(q),rotL(t);
                    else rotR(t),rotL(t);
                }
            }
        }
    }

    inline Node* create(){
        return &pool[ptr++];
    }

    inline Node* create(int idx,T v){
        return &(pool[ptr++]=Node(idx,v,M::ei()));
    }

    Node* expose(Node *t){
        Node *rp=nullptr;
        for(Node *c=t;c;c=c->p){
            splay(c);
            c->r=rp;
            recalc(c);
            rp=c;
        }
        splay(t);
        return rp;
    }

    void link(Node *par,Node *c){
        evert(c);
        expose(par);
        c->p=par;
        par->r=c;
    }

    void cut(Node *c){
        expose(c);
        Node *par=c->l;
        c->l=nullptr;
        par->p=nullptr;
    }

    void evert(Node *t){
        expose(t);
        toggle(t);
        eval(t);
    }

    Node *root(Node *t){
        expose(t);
        while(t->l) t=t->l;
        splay(t);
        return t;
    }
public:
    LinkCutTree():pool(LIM),ptr(0){}
    LinkCutTree(size_t N)
    :pool(LIM),ptr(0),nodes(N){
        for(size_t i=0;i<N;i++){
            nodes[i]=create(i,M::ti());
        }
    }
    LinkCutTree(vector<T> v)
    :pool(LIM),ptr(0),nodes(v.size()){
        for(size_t i=0;i<v.size();i++){
            nodes[i]=create(i,v[i]);
        }
    }
    size_t insert(T v){
        nodes.emplace_back(create(nodes.size(),v));
        return nodes.size()-1;
    }
    void set_val(size_t p,T v){
        eval(nodes[p]);
        nodes[p]->val=v;
    }
    void link(size_t par,size_t c){
        link(nodes[par],nodes[c]);
    }
    void cut(size_t par,size_t c){
        assert(is_connected(par,c));
        evert(nodes[par]);
        cut(nodes[c]);
    }
    void evert(size_t v){
        evert(nodes[v]);
    }
    bool is_connected(size_t a,size_t b){
        return root(nodes[a])==root(nodes[b]);
    }
    size_t lca(size_t a,size_t b){
        expose(nodes[a]);
        return expose(nodes[b])->idx;
    }
    //[root,b]
    T query(size_t b){
        expose(nodes[b]);
        return nodes[b]->dat;
    }
    //[a,b]
    T query(size_t a,size_t b){
        evert(nodes[a]);
        return query(b);
    }
    //[root,b]
    void update(size_t b,E v){
        expose(nodes[b]);
        propagate(nodes[b],v);
        eval(nodes[b]);
    }
    //[a,b]
    void update(size_t a,size_t b,E v){
        evert(nodes[a]);
        update(b,v);
    }
};
struct RupdqRsumq {
    using T = pair<ll,ll>;
    using E = pair<ll,ll>;
    static T ti() { return {0,0}; }
    static E ei() { return {INF,INF}; }
    static T f(const T& l, const T& r) { return {l.first+r.first,l.second+r.second}; }
    static T g(const T& l, const E& r,const size_t& len) { return r==ei()?l:T(r.first*len,r.second*len);  }
    static E h(const E& l, const E& r) { return r==ei()? l:r;  }
};

signed main(){
  cin.tie(0);
  ios::sync_with_stdio(false);
  ll N,Q;cin>>N>>Q;
  LinkCutTree<RupdqRsumq> LCT(N);
  vector<pair<ll,ll>> color[N];
  for(ll i=0;i<N-1;i++){
    ll a,b,c,d;cin>>a>>b>>c>>d;a--;b--;c--;
    ll e=LCT.insert({d,0});
    color[c].push_back({e,d});
    LCT.link(a,e);
    LCT.link(e,b);
  }
  vector<tuple<ll,ll,ll,ll,ll> > query(Q);
  for(ll q=0;q<Q;q++){
    ll x,y,u,v;cin>>x>>y>>u>>v;x--;u--;v--;
    query[q]=make_tuple(x,y,u,v,q);
  }
  sort(query.begin(),query.end());
  ll ans[Q];
  ll cnow=-1;
  for(ll i=0;i<Q;i++){
    ll x,y,u,v,q;tie(x,y,u,v,q)=query[i];
    if(x!=cnow){
      if(cnow>=0){
        for(auto u:color[cnow]){
          LCT.update(u.first,u.first,{u.second,0});
        }
      }
      for(auto u:color[x]){
        LCT.update(u.first,u.first,{0ll,1ll});
      }
      cnow=x;
    }
    auto aa=LCT.query(u,v);
    //debug(aa.first);
    ans[q]=aa.first+aa.second*y;
  }
  for(ll q=0;q<Q;q++){
    cout<<ans[q]<<endl;
  }
  return 0;
}


Measured memory_bytes: 121840