#include <bits/stdc++.h>
using namespace std;
#define tag "spoj"
#define maxn 100007
#define maxc 0
#define maxlog 17
#define oo 1000000007
#define mid ((l+r)>>1)
#define meset(a,x) memset(a,x,sizeof(a))
#define loop(x) for(int LoOpEr=1;LoOpEr<=x;LoOpEr++)
///>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

#define mid ((l+r)>>1)
struct pst{
    int cnt;
    int sum;
    pst *left,*right;

    pst(const int &c,const int &s,pst *l,pst *r): cnt(c), sum(s), left(l), right(r) {};

    pst* insert(const int &l,const int &r,const int &add,const int &val)
    {
        if(add<l || add>r) return this;

        if(l==r) return new pst(cnt+1,sum+val,0,0);

        return new pst(cnt+1,sum+val,left->insert(l,mid,add,val),right->insert(mid+1,r,add,val));
    }

    int getcnt(const int &l,const int &r,const int &x)
    {
        if(x<l || x>r) return 0;

        if(l==r) return cnt;

        return left->getcnt(l,mid,x) + right->getcnt(mid+1,r,x);
    }

    int getsum(const int &l,const int &r,const int &x)
    {
        if(x<l || x>r) return 0;

        if(l==r) return sum;

        return left->getsum(l,mid,x) + right->getsum(mid+1,r,x);
    }
} *null = new pst(0,0,0,0);

struct nodeTree{
    pst* root;
    int anc[22];
    int depth;
    int len;
};

int n,m;

struct neigh{
    int ver,color,cost;
};
vector<neigh> adj[maxn];
#define add_edge(u,v,c,d) adj[u].push_back({v,c,d}),adj[v].push_back({u,c,d})

vector<nodeTree> infor;
#define root(u) infor[u].root
#define par(u) infor[u].anc[0]
#define ances(u,i) infor[u].anc[i]
#define depth(u) infor[u].depth
#define len(u) infor[u].len

void dfs(const int &u,const int &parent,const int &depth,const int &color,const int &cost)
{
    root(u)=root(parent)->insert(1,n,color,cost);
    par(u)=parent;
    depth(u)=depth;
    len(u)=len(parent)+cost;

    for(int i=1;1<<i<n;i++) ances(u,i)=ances(ances(u,i-1),i-1);

    for(const neigh& e: adj[u])
        if(e.ver!=parent)
            dfs(e.ver,u,depth+1,e.color,e.cost);
}

int lca(int x,int y)
{
    if(depth(x)<depth(y)) swap(x,y);
    while(depth(x)>depth(y)) x=ances(x,(int)log2(depth(x)-depth(y)));

    int lg=log2(depth(x));

    while(x!=y)
    {
        while(lg>0 && ances(x,lg)==ances(y,lg)) --lg;
        x=ances(x,lg),y=ances(y,lg);
    }
    return x;
}

int query(const int &u,const int &v,const int &x,const int &y)
{
    int lcanc=lca(u,v);

    int cnt=root(u)->getcnt(1,n,x) + root(v)->getcnt(1,n,x) - 2*root(lcanc)->getcnt(1,n,x);
    int sum=root(u)->getsum(1,n,x) + root(v)->getsum(1,n,x) - 2*root(lcanc)->getsum(1,n,x);

    return len(u)+len(v)-2*len(lcanc) - sum + y*cnt;
}

void data()
{
    infor.resize(n+1);
    for(auto &mation: infor) meset(mation.anc,0);
}
int main()
{
    #ifdef dmdd
    freopen(tag".inp","r",stdin); freopen(tag".out","w",stdout);
    #endif //dmdd
    ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);

    cin>>n>>m;
    data();

    int u,v,c,d;

    for(int i=1;i<n;i++) cin>>u>>v>>c>>d,add_edge(u,v,c,d);

    null->left=null->right=null;
    root(0)=null;

    dfs(1,0,1,0,0);

    loop(m) cin>>c>>d>>u>>v,cout<<query(u,v,c,d)<<"\n";

    return 0;
}


Measured memory_bytes: 90880