// 2020-08-04 15:02:06
#include<bits/stdc++.h>
#ifdef LOCAL
#include "lib/debug.hpp"
#else
#define debug(...) 1
#endif
#define ALL(a) (a).begin(), (a).end()
#define RALL(a) (a).rbegin(), (a).rend()
#define rep(i, n) REP(i, 0, (n))
#define repc(i, n) REPC(i, 0, (n))
#define REP(i, n, m) for (int i = (int)(n); i < (int)(m); i++)
#define REPC(i, n, m) for (int i = (int)(n); i <= (int)(m); i++)
#define REPCM(i, n, m) for (int i = (int)(n); i >= (int)(m); i--)
using namespace std;
using ll = long long;
using ld = long double;
using pr = pair<ll, ll>;
using vll = vector<ll>;
using vpr = vector<pr>;
using P = pair<int, int>;
template<class T> inline bool chmin(T& a, const T& b) { if (a > b) { a = b; return true; } else return false; }
template<class T> inline bool chmax(T& a, const T& b) { if (a < b) { a = b; return true; } else return false; }

const int MAX_N = 100010;
struct LCA {
  int N, K;
  std::vector<std::vector<int> > G, parent;
  std::vector<int> depth;

  LCA(int n) : N(n) {
    K = (int)ceil(log2(N));
    G.resize(N);
    parent.resize(std::max(K, 1), std::vector<int>(N, -1));
    depth.resize(N, -1);
  }

  void add_edge(int u, int v) {
    G[u].push_back(v);
    G[v].push_back(u);
  }

  void dfs(int u, int p, int d) {
    if(depth[u] >= 0) return;
    parent[0][u] = p;
    depth[u] = d;
    for(const auto& v : G[u]) {
      dfs(v, u, d+1);
    }
  }

  void set_root(int u) {
    dfs(u, -1, 0);
    for(int k = 1; k < K; k++) {
      for(int i = 0; i < N; i++) {
        if(parent[k-1][i] == -1) {
          parent[k][i] = -1;
        } else {
          parent[k][i] = parent[k-1][parent[k-1][i]];
        }
      }
    }
  }

  int query(int u, int v) {
    if(depth[u] < depth[v]) std::swap(u, v);
    for(int i = K-1; i >= 0; i--) {
      if(parent[i][u] != -1 && depth[parent[i][u]] >= depth[v]) {
        u = parent[i][u];
      }
    }
    if(u == v) return u;
    for(int i = K-1; i >= 0; i--) {
      if(parent[i][u] != parent[i][v]) {
        u = parent[i][u];
        v = parent[i][v];
      }
    }
    return parent[0][u];
  }
};
struct Edge {
  int to, c, d;
  Edge(int to_, int c_, int d_) : to(to_), c(c_), d(d_) {}
};
using T3 = tuple<int, int, int>;
using T4 = tuple<int, int, int, int>;
int ccnt[MAX_N], cdist[MAX_N];
vector<P> vq[MAX_N]; // x, y
vector<Edge> G[MAX_N];
T4 Q[MAX_N];
map<T3, int> mp; // v, x, y

void dfs(int u, int p, int dist) {
  for(const P& q : vq[u]) {
    int x = q.first, y = q.second;
    mp[T3(u, x, y)] = dist - cdist[x] + ccnt[x] * y;
  }
  for(const Edge& e : G[u]) if(e.to != p) {
    ccnt[e.c] += 1;
    cdist[e.c] += e.d;
    dfs(e.to, u, dist + e.d);
    ccnt[e.c] -= 1;
    cdist[e.c] -= e.d;
  }
}
void answer() {
  int n, q;
  cin >> n >> q;
  LCA lca(n);
  rep(i, n-1) {
    int a, b, c, d;
    cin >> a >> b >> c >> d;
    a--; b--; c--;
    G[a].emplace_back(Edge(b, c, d));
    G[b].emplace_back(Edge(a, c, d));
    lca.add_edge(a, b);
  }
  lca.set_root(0);
  rep(i, q) {
    int x, y, u, v;
    cin >> x >> y >> u >> v;
    x--; u--; v--;
    Q[i] = T4(x, y, u, v);
    int p = lca.query(u, v);
    vq[u].emplace_back(P(x, y));
    vq[v].emplace_back(P(x, y));
    vq[p].emplace_back(P(x, y));
  }
  dfs(0, -1, 0);
  rep(i, q) {
    int x, y, u, v;
    tie(x, y, u, v) = Q[i];
    int p = lca.query(u, v);
    cout << mp[T3(u, x, y)] + mp[T3(v, x, y)] - 2 * mp[T3(p, x, y)] << '\n';
  }
}
int main() {
  std::ios::sync_with_stdio(false);
  std::cin.tie(0);
  answer();
  return 0;
}

Measured memory_bytes: 53596