#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
typedef vector<int> VI;
typedef vector<VI> VVI;
typedef vector<long long> VL;
typedef vector<vector<long long>> VVL;
typedef vector<string> VS;
typedef pair<int,int> P;
typedef tuple<int,int,int> tpl;

#define ALL(a)  (a).begin(),(a).end()
#define SORT(c) sort((c).begin(),(c).end())
#define REVERSE(c) reverse((c).begin(),(c).end())
#define EXIST(m,v) (m).find((v)) != (m).end()
#define LB(a,x) lower_bound((a).begin(), (a).end(), x) - (a).begin()
#define UB(a,x) upper_bound((a).begin(), (a).end(), x) - (a).begin()

#define FOR(i,a,b) for(int i=(a);i<(b);++i)
#define REP(i,n)  FOR(i,0,n)
#define RFOR(i,a,b) for(int i=(a)-1;i>=(b);--i)
#define RREP(i,n) RFOR(i,n,0)

#define en "\n"

constexpr double EPS = 1e-9;
constexpr double PI  = 3.1415926535897932;
constexpr int INF = 2147483647;
constexpr long long LINF = 1LL<<60;
constexpr long long MOD = 1000000007; // 998244353;

template<class T> inline bool chmax(T& a, T b) { if (a < b) { a = b; return true; } return false; }
template<class T> inline bool chmin(T& a, T b) { if (a > b) { a = b; return true; } return false; }

struct Edge{
    int from, to;
    int cost=1;
    int color, id;

    Edge(int from, int to, int cost, int color, int id): from(from), to(to), cost(cost), color(color), id(id) {}
    Edge() {}

    friend istream &operator>>(istream  &input, Edge &e ){ 
        input >> e.from >> e.to;
        e.from--; e.to--;
        return input;            
    }

    Edge rev(void){
        return Edge(to, from, cost, color, id);
    }
};

vector<vector<Edge>> edge;
vector<bool> vis;
vector<Edge> euler;

int N, LOGN; // floor(log2(N))
VVI tab;
VI depth;

void doubling(){
    for(int i=0; i<N; i++) tab[i][0] = -1;

    for(int i=0; i<N; i++){
        for(Edge& e : edge[i]){
            if(depth[e.from] < depth[e.to]) continue;
            tab[e.from][0] = e.to;
        }
    }

    for(int k=0; k<LOGN; k++)
        for(int i=0; i<N; i++){
            if(tab[i][k] == -1) tab[i][k+1] = -1;
            else tab[i][k+1] = tab[tab[i][k]][k];
        }
}

int LCA(int u, int v){
    if(depth[v] < depth[u]) swap(u,v);
    int k = depth[v] - depth[u];
    for(int i=0; i<=LOGN; i++){
        if(k & 1<<i) v = tab[v][i];
    }
    if(u == v) return u;
    for(int i=LOGN; i>=0; i--){
        if(tab[u][i] != tab[v][i]){
            u = tab[u][i];
            v = tab[v][i];
        }
    }
    return tab[u][0];
}

VI dist;
void dfs(Edge e, int d){
    vis[e.to] = true;
    depth[e.to] = d;
    dist[e.to] = dist[e.from] + e.cost;
    for(Edge& ch : edge[e.to]){
        if(vis[ch.to]) continue;
        dfs(ch, d+1);
    }
    return;
}

vector<int> id;
void eulerTour(Edge e){
    vis[e.to] = true;
    if(e.from != -1){
        e.id = euler.size();
        euler.emplace_back(e);
        id[e.to] = e.id;
    }
    for(Edge& ch : edge[e.to]){
        if(vis[ch.to]) continue;
        eulerTour(ch);
    }
    if(e.from != -1){
        Edge e2 = e.rev(); e2.id = euler.size(); e2.cost = -e.cost;
        euler.emplace_back(e2);
    }
    return;
}

VVI id_per_color, sum, num;

int distance(int color, int len, int v){
    if(v == 0) return 0;
    int l = -1, r = id_per_color[color].size();
    while(r-l>1){
        int x = (l+r)/2;
        if(id_per_color[color][x] <= id[v]) l = x;
        else r = x;
    }
    int n = num[color][r], s = sum[color][r];
    return dist[v] - s + n*len;
}

int query(int x, int y, int u, int v){
    int r = LCA(u,v);
    int du = distance(x, y, u);
    int dv = distance(x, y, v);
    int dr = distance(x, y, r);
    return du + dv - 2*dr;
}

void Main(){
    int Q; cin >> N >> Q;
    edge.assign(N,{});
    REP(i,N-1){
        int a,b,c,d; cin >> a >> b >> c >> d; a--; b--; c--;
        Edge e(a,b,d,c,i);
        edge[e.from].emplace_back(e);
        edge[e.to].emplace_back(e.rev());
    }

    vis.assign(N,0);depth.resize(N);dist.resize(N,0); dfs(Edge(0,0,0,0,0),0);
    LOGN = floor(log2(N));tab.resize(N,VI(LOGN+1,-1)); doubling();

    vis.assign(N,0);id.resize(N); eulerTour(Edge(-1,0,0,0,0));

    id_per_color.resize(N);sum.resize(N,{0});num.resize(N,{0});
    for(auto& e : euler){
        id_per_color[e.color].push_back(e.id);
        sum[e.color].push_back(e.cost);
        num[e.color].push_back(2*(e.cost>0)-1);
    }
    REP(i,N){
        int k = sum[i].size();
        REP(j,k-1) sum[i][j+1] += sum[i][j];
        REP(j,k-1) num[i][j+1] += num[i][j];
    }

    REP(_,Q){
        int x,y,u,v; cin >> x >> y >> u >> v; x--; u--; v--;
        int ans = query(x,y,u,v);
        cout << ans << en;
    }
    return;
}

int main(void){
    cin.tie(0);cout.tie(0);ios_base::sync_with_stdio(0);cout<<fixed<<setprecision(15);
    int t=1; //cin>>t;
    REP(_,t) Main();
    return 0;
}

Measured memory_bytes: 50308