#include <bits/stdc++.h>
#define For(i, a, b) for(int (i)=(int)(a); (i)<(int)(b); ++(i))
#define rFor(i, a, b) for(int (i)=(int)(a)-1; (i)>=(int)(b); --(i))
#define rep(i, n) For((i), 0, (n))
#define rrep(i, n) rFor((i), (n), 0)
#define fi first
#define se second
using namespace std;
typedef long long lint;
typedef unsigned long long ulint;
typedef pair<int, int> pii;
typedef pair<lint, lint> pll;
template<class T> bool chmax(T &a, const T &b){if(a<b){a=b; return true;} return false;}
template<class T> bool chmin(T &a, const T &b){if(a>b){a=b; return true;} return false;}
template<class T> T div_floor(T a, T b){
    if(b < 0) a *= -1, b *= -1;
    return a>=0 ? a/b : (a+1)/b-1;
}
template<class T> T div_ceil(T a, T b){
    if(b < 0) a *= -1, b *= -1;
    return a>0 ? (a-1)/b+1 : a/b;
}

constexpr lint mod = 1e9+7;
constexpr lint INF = mod * mod;
constexpr int MAX = 100010;

template<typename T, typename E, typename F, typename G> struct LinkCutTree{
    struct Node{
        Node *par_ptr, *left_ptr, *right_ptr;
        int idx;
        bool rev;
        T val, sum;

        Node(): idx(-1), par_ptr(nullptr), left_ptr(nullptr), right_ptr(nullptr),
        rev(false), val(T{}), sum(T{}){}

        bool is_root(){
            return !par_ptr || (par_ptr->left_ptr != this && par_ptr->right_ptr != this);
        }

        void print_data(){
            int p = par_ptr ? par_ptr->idx : -1;
            int l = left_ptr ? left_ptr->idx : -1;
            int r = right_ptr ? right_ptr->idx : -1;
            printf("id=%d, p=%d, l=%d, r=%d, rev=%d, val=%lld, sum=%lld\n", idx, p, l ,r, rev, val, sum);
        }
    };
    
    int n;
    vector<Node> nodes;
    F f;
    G g;

    LinkCutTree(int n, T et, F f, G g): n(n), f(f), g(g){
        nodes.resize(n);
        rep(i, n){
            nodes[i].idx = i;
            nodes[i].val = nodes[i].sum = et;
        }
    }

    void toggle(Node *node){
        if(!node->rev) return;
        if(node->left_ptr) node->left_ptr->rev ^= true;
        if(node->right_ptr) node->right_ptr->rev ^= true;
        swap(node->left_ptr, node->right_ptr);
        node->rev = false;
    }

    void pull(Node *node){
        node->sum = node->val;
        if(node->left_ptr) node->sum = f(node->left_ptr->sum, node->sum);
        if(node->right_ptr) node->sum = f(node->sum, node->right_ptr->sum);
    }

    void rotl(Node *node){
        Node *par = node->par_ptr, *grand_par = par->par_ptr;
        if((par->right_ptr = node->left_ptr)) node->left_ptr->par_ptr = par;
        node->left_ptr = par; par->par_ptr = node;
        pull(par); pull(node);
        if((node->par_ptr = grand_par)){
            if(grand_par->left_ptr == par) grand_par->left_ptr = node;
            if(grand_par->right_ptr == par) grand_par->right_ptr = node;
            pull(grand_par);
        }
    }

    void rotr(Node *node){
        Node *par = node->par_ptr, *grand_par = par->par_ptr;
        if((par->left_ptr = node->right_ptr)) node->right_ptr->par_ptr = par;
        node->right_ptr = par; par->par_ptr = node;
        pull(par); pull(node);
        if((node->par_ptr = grand_par)){
            if(grand_par->left_ptr == par) grand_par->left_ptr = node;
            if(grand_par->right_ptr == par) grand_par->right_ptr = node;
            pull(grand_par);
        }
    }

    void toggle_all(Node *node){
        if(node->is_root()){
            toggle(node);
            return;
        }
        toggle_all(node->par_ptr);
        toggle(node);
    }

    void splay(int i){
        Node *node = &nodes[i];
        toggle_all(node);
        while(!node->is_root()){
            Node *par = node->par_ptr;
            if(par->is_root()){
                if(par->right_ptr == node) rotl(node);
                else rotr(node);
                return; 
            }

            Node *grand_par = par->par_ptr;
            if(par->left_ptr == node){
                if(grand_par->left_ptr == par) rotr(par), rotr(node);
                else rotr(node), rotl(node);
            }
            else{
                if(grand_par->right_ptr == par) rotl(par), rotl(node);
                else rotl(node), rotr(node);
            }
        }
    }

    Node *expose(int i){
        Node *child = nullptr;
        for(Node *par=&nodes[i]; par; par=par->par_ptr){
            splay(par->idx);
            par->right_ptr = child;
            pull(par);
            child = par;
        }
        splay(i);
        return child;
    }

    void link(int child, int par){
        expose(child);
        expose(par);
        nodes[child].par_ptr = &nodes[par];
        nodes[par].right_ptr = &nodes[child];
        pull(&nodes[par]);
    }

    void cut(int child){
        expose(child);
        Node *par = nodes[child].left_ptr;
        nodes[child].left_ptr = nullptr;
        par->par_ptr = nullptr;
        pull(&nodes[child]);
    }

    void evert(int i){
        expose(i);
        nodes[i].rev = true;
        toggle(&nodes[i]);
    }

    void add_edge(int child, int par){
        evert(par);
        evert(child);
        link(child, par);
    }

    void del_edge(int child, int par){
        evert(par);
        cut(child);
    }

    void update_val(int i, E x){
        evert(i);
        nodes[i].val = g(nodes[i].val, x);
        pull(&nodes[i]);
    }

    T get_path_sum(int u, int v){
        evert(u);
        expose(v);
        return nodes[v].sum;
    }
};

struct edge{
    int id, u, v; lint cost;
    edge(int i, int u, int v, lint c): id(i), u(u), v(v), cost(c){}
};

struct query{
    int id, u, v; lint y;
    query(int i, int u, int v, lint y): id(i), u(u), v(v), y(y){}
};

int main(){
    int n, q;
    scanf("%d%d", &n, &q);
    auto g = [](lint x, lint y){return y;};
    LinkCutTree<lint, lint, decltype(plus<>()), decltype(g)> lct_sum(2*n-1, 0, plus<>(), g);
    LinkCutTree<lint, lint, decltype(plus<>()), decltype(g)> lct_num(2*n-1, 0, plus<>(), g);
    vector<edge> E[MAX];
    vector<query> Q[MAX];
    rep(i, n-1){
        int a, b, c; lint d;
        scanf("%d%d%d%lld", &a, &b, &c, &d);
        --a; --b;
        E[c].emplace_back(i+n, a, b, d);

        lct_sum.add_edge(a, i+n);
        lct_sum.add_edge(i+n, b);
        lct_sum.update_val(i+n, d);
        
        lct_num.add_edge(a, i+n);
        lct_num.add_edge(i+n, b);
    }
    rep(i, q){
        int x, u, v; lint y;
        scanf("%d%lld%d%d", &x, &y, &u, &v);
        --u; --v;
        Q[x].emplace_back(i, u, v, y);
    }

    lint ans[q];
    rep(c, MAX)if(!Q[c].empty()){
        for(auto &e: E[c]){
            lct_sum.update_val(e.id, 0);
            lct_num.update_val(e.id, 1);
        }
        for(auto [id, u, v, y]: Q[c]){
            ans[id] = lct_sum.get_path_sum(u, v) + y * lct_num.get_path_sum(u, v);
        }
        for(auto &e: E[c]){
            lct_sum.update_val(e.id, e.cost);
            lct_num.update_val(e.id, 0);
        }
    }

    rep(i, q) printf("%lld\n", ans[i]);
}

Measured memory_bytes: 35224