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

void solve(std::istream &in, std::ostream &out);

int main() {
#ifdef LOCAL
  freopen("../IO/f.in", "r", stdin);
//  freopen("../IO/f.out", "w", stdout);
#else
  std::ios_base::sync_with_stdio(false);
  std::cin.tie(nullptr);
  std::cout.tie(nullptr);
#endif
  solve(std::cin, std::cout);
  return 0;
}
template <typename T>
struct fenwick {
  int n;
  vector<T> f;

  fenwick() = default;

  fenwick(int N) {
    n = N;
    f.assign(N, T(0));
  }

  fenwick(vector<T> a) {
    n = a.size();
    f.assign(n, T(0));
    for (int i = 0; i < n; i++) add(i, a[i]);
  }

  void add(int x, T y) {
    for (; x < n; x |= x + 1) f[x] += y;
  }

  T get(int x) {
    T res(0);
    for (; x >= 0; x = (x & (x + 1)) - 1) res += f[x];
    return res;
  }

  T get(int l, int r) {
    return get(r) - get(l - 1);
  }
};
int bsr(uint x) {
  if (x == 0) return -1;
  return 31 - __builtin_clz(x);
}

template <class T>
struct SparseTable {
  int logarithm;
  vector<vector<T>> rmq;
  std::function<T(T, T)> op;
  SparseTable() {}

  SparseTable(const vector<T> &v, const std::function<T(T, T)> &op) : op(op) {
    int n = int(v.size());
    if (n == 0) return;
    logarithm = bsr(uint(n)) + 1;
    rmq = vector<vector<T>>(logarithm);
    rmq[0] = v;
    int l = 1;
    for (int s = 1; s < logarithm; ++s) {
      rmq[s] = vector<T>(n);
      for (int i = 0; i < n - l; ++i) {
        rmq[s][i] = op(rmq[s - 1][i], rmq[s - 1][i + l]);
      }
      l <<= 1;
    }
  }
  // [l, r), e = identity element
  T query(int l, int r, T e) const {
    assert(l <= r);
    if (l == r) return e;
    int u = bsr(uint(r - l));
    return op(rmq[u][l], rmq[u][r - (1 << u)]);
  }
};


struct LCA_RMQ {
  vector<int> euler_tour;
  vector<int> edge_in;
  vector<int> edge_out;
  vector<int> w;
  SparseTable<int> rmq;
  vector<int> first_entry;
  vector<int> depth;

  std::function<int(int, int)> op = [&](int a, int b) {
    return depth[a] < depth[b] ? a : b;
  };

  template <class E>
  LCA_RMQ(const vector<vector<E>> &g, int root) {
    first_entry.resize(g.size());
    depth.resize(g.size());
    edge_in.resize(g.size() - 1);
    edge_out.resize(g.size() - 1);
    w.resize(g.size(), 0);
    euler_tour.reserve(2 * g.size());
    dfs(g, root, -1, 0, 0);
    rmq = SparseTable<int>(euler_tour, op);
  }

  int query(int a, int b) {
    int l = first_entry[a];
    int r = first_entry[b];
    if (l > r) swap(l, r);
    return rmq.query(l, r + 1, -1);
  }

  template <class E>
  void dfs(const vector<vector<E>> &g, int v, int p, int h, int we) {
    w[v] = we;
    first_entry[v] = euler_tour.size();
    depth[v] = h;
    euler_tour.push_back(v);
    for (E e : g[v]) {
      if (e.to == p) {
        continue;
      }
      edge_in[e.id] = euler_tour.size();
      dfs(g, e.to, v, h + 1, we + e.w);
      edge_out[e.id] = euler_tour.size();
      euler_tour.push_back(v);
    }
  }
};

struct edge_t {
  int to, w, id;
  edge_t() = default;
  edge_t(int to, int w, int id) : to(to), w(w), id(id) {}
};

struct query_t {
  int y, u, v, id;
  query_t() = default;
  query_t(int y, int u, int v, int id) : y(y), u(u), v(v), id(id) {}
};

void solve(std::istream &in, std::ostream &out) {
  int N, Q;
  in >> N >> Q;
  vector<vector<int>> ids(N);
  vector<int> cost(N - 1);
  vector<vector<edge_t>> graph(N);
  for (int i = 0; i < N - 1; ++i) {
    int a, b, c;
    in >> a >> b >> c >> cost[i];
    --a;
    --b;
    graph[a].emplace_back(b, cost[i], i);
    graph[b].emplace_back(a, cost[i], i);
    ids[c].push_back(i);
  }
  vector<int> qans(Q, 0);
  vector<vector<query_t>> Qs(N);
  for (int i = 0; i < Q; ++i) {
    int x, y, u, v;
    in >> x >> y >> u >> v;
    --u;
    --v;
    Qs[x].emplace_back(y, u, v, i);
  }
  LCA_RMQ al(graph, 0);
  fenwick<int> bit1(2 * N + 1), bit2(2 * N + 1);
  for (int i = 0; i < N; ++i) {
    if (Qs[i].empty()) {
      continue;
    }
    for (int id : ids[i]) {
      bit1.add(al.edge_in[id], 1);
      bit1.add(al.edge_out[id], -1);
      bit2.add(al.edge_in[id], cost[id]);
      bit2.add(al.edge_out[id], -cost[id]);
    }
    for (auto query : Qs[i]) {
      int y = query.y, u = query.u, v = query.v, id = query.id;
      int p = al.query(u, v);
      int ans = al.w[u] + al.w[v] - 2 * al.w[p];
      ans += y * (bit1.get(al.first_entry[u]) + bit1.get(al.first_entry[v]) - 2 * bit1.get(al.first_entry[p]));
      ans -= bit2.get(al.first_entry[u]) + bit2.get(al.first_entry[v]) - 2 * bit2.get(al.first_entry[p]);
      qans[id] = ans;
    }
    for (int id : ids[i]) {
      bit1.add(al.edge_in[id], -1);
      bit1.add(al.edge_out[id], 1);
      bit2.add(al.edge_in[id], -cost[id]);
      bit2.add(al.edge_out[id], cost[id]);
    }
  }
  for (int i = 0; i < Q; ++i) {
    out << qans[i] << "\n";
  }
}


Measured memory_bytes: 37432