#include<cstdio>
#include<algorithm>
#include<iostream>
#include<vector>
using namespace std;
#define ll long long
const int maxn=1e5+5;
vector<int> nei[maxn];
struct Edge
{
    int u,v,d,which;
};
vector<Edge> edges[maxn];
int fa[maxn],sz[maxn],depth[maxn],heavy_son[maxn];
void dfs1(int root)
{
    sz[root]=1;
    int weight=0,son=-1;
    for(int i=0;i<(int)nei[root].size();i++)
    {
        int next=nei[root][i];
        if(next==fa[root]) continue;
        fa[next]=root;
        depth[next]=depth[root]+1;
        dfs1(next);
        if(sz[next]>weight)
        {
            weight=sz[next];
            son=next;
        }
        sz[root]+=sz[next];
    }
    heavy_son[root]=son;
    return;
}
int top[maxn],dfn[maxn],cnt;
void dfs2(int root,int _top)
{
    top[root]=_top;
    dfn[root]=++cnt;
    int son=heavy_son[root];
    if(son!=-1)
        dfs2(son,_top);
    for(int i=0;i<(int)nei[root].size();i++)
    {
        int next=nei[root][i];
        if(next!=fa[root]&&next!=son)
            dfs2(next,next);
    }
    return;
}
struct Segment_Tree
{
    struct node
    {
        int l,r,sum;
    }tree[4*maxn];
    void push_up(int cur)
    {
        tree[cur].sum=tree[cur<<1].sum+tree[cur<<1|1].sum;
    }
    void build(int l,int r,int cur)
    {
        tree[cur].l=l;
        tree[cur].r=r;
        if(l==r)
        {
            tree[cur].sum=0;
            return;
        }
        int mid=(l+r)>>1;
        build(l,mid,cur<<1);
        build(mid+1,r,cur<<1|1);
        push_up(cur);
        return;
    }
    void add(int pos,int val,int cur)
    {
        if(tree[cur].l==pos&&tree[cur].r==pos)
        {
            tree[cur].sum+=val;
            return;
        }
        if(tree[cur].l>pos||tree[cur].r<pos)
            return;
        add(pos,val,cur<<1);
        add(pos,val,cur<<1|1);
        push_up(cur);
        return;
    }
    int query(int l,int r,int cur)
    {
        if(tree[cur].l>=l&&tree[cur].r<=r)
            return tree[cur].sum;
        if(tree[cur].l>r||tree[cur].r<l)
            return 0;
        return query(l,r,cur<<1)+query(l,r,cur<<1|1);
    }
    int solve(int u,int v)
    {
        int res=0;
        while(top[u]!=top[v])
        {
            if(depth[top[u]]<depth[top[v]])
                swap(u,v);
            res+=query(dfn[top[u]],dfn[u],1);
            u=fa[top[u]];
        }
        if(depth[u]<depth[v])
            swap(u,v);
        res+=query(dfn[v],dfn[u],1);
        res-=query(dfn[v],dfn[v],1);
        return res;
    }
}num,val;
struct event
{
    int u,v,d,id;
};
vector<event> queries[maxn];
int ans[maxn];
int main()
{
    int n,q;
    scanf("%d%d",&n,&q);
    int maxc=0;
    for(int i=1;i<n;i++)
    {
        int u,v,c,d;
        scanf("%d%d%d%d",&u,&v,&c,&d);
        nei[u].push_back(v);
        nei[v].push_back(u);
        edges[c].push_back((Edge){u,v,d,-1});
        maxc=max(maxc,c);
    }
    dfs1(1);
    dfs2(1,1);
    val.build(1,n,1);
    for(int i=1;i<=maxc;i++)
        for(int j=0;j<(int)edges[i].size();j++)
        {
            int u=edges[i][j].u,v=edges[i][j].v;
            edges[i][j].which=(depth[u]>depth[v]?u:v);
        }
    for(int i=1;i<=maxc;i++)
        for(int j=0;j<(int)edges[i].size();j++)
            val.add(dfn[edges[i][j].which],edges[i][j].d,1);
    for(int i=1;i<=q;i++)
    {
        int u,v,c,d;
        scanf("%d%d%d%d",&c,&d,&u,&v);
        queries[c].push_back((event){u,v,d,i});
        ans[i]=val.solve(u,v);
    }
    for(int i=1;i<=maxc;i++)
        for(int j=0;j<(int)edges[i].size();j++)
            val.add(dfn[edges[i][j].which],-edges[i][j].d,1);
    num.build(1,n,1);
    for(int i=1;i<=maxc;i++)
    {
        for(int j=0;j<(int)edges[i].size();j++)
        {
            val.add(dfn[edges[i][j].which],edges[i][j].d,1);
            num.add(dfn[edges[i][j].which],1,1);
        }
        for(int j=0;j<(int)queries[i].size();j++)
        {
            event cur=queries[i][j];
            ans[cur.id]-=val.solve(cur.u,cur.v);
            ans[cur.id]+=num.solve(cur.u,cur.v)*cur.d;
        }
        for(int j=0;j<(int)edges[i].size();j++)
        {
            val.add(dfn[edges[i][j].which],-edges[i][j].d,1);
            num.add(dfn[edges[i][j].which],-1,1);
        }
    }
    for(int i=1;i<=q;i++)
        printf("%d\n",ans[i]);
    return 0;
}
/*
5 3
1 2 1 10
1 3 2 20
2 4 4 30
5 2 1 40
1 100 1 4
1 100 1 5
3 1000 3 4
 */


Measured memory_bytes: 33096