#include <bits/stdc++.h>
template<typename T>
class fixed_point : T {
  public:
    explicit constexpr fixed_point (T&& t)
      : T(std::forward<T>(t)) {}
    template<typename... Args>
    constexpr decltype(auto) operator()(Args&&... args) const
      {return T::operator()(*this, std::forward<Args>(args)...);}
};
template<typename T>
static inline constexpr decltype(auto) fix (T&& t) {
  return fixed_point<T>{std::forward<T>(t)};
}
// Dependent libraries: Combinator.
class heavy_light_decomposition {
    struct edge {size_t to;};
    bool built; size_t n;
    std::vector<std::vector<edge>> graph;
    std::vector<size_t>            prt, sub, ord, head;
  public:
    using edge_type = edge;
    heavy_light_decomposition(size_t n) :
      built(false), n(n),
      graph(n), prt(n), sub(n, 1), ord(n), head(n) {}
    // Insert an edge.
    void insert (size_t u, size_t v) {
      assert(!built);
      graph.at(u).push_back({v});
      graph.at(v).push_back({u});
    }
    // Deflag the built flag.
    void deflag () {
      assert(built);
      built = false;
    }
    // Build an HL Decomposition.
    void build (size_t root = 0) {
      assert(!built); built = true;
      fix ([&](auto dfs, size_t crr, size_t p) -> void {
        prt.at(crr) = p;
        for (auto& e : graph.at(crr)) {
          if (e.to == p) continue;
          dfs(e.to, crr);
          sub.at(crr) += sub.at(e.to);
          if (sub.at(e.to) > sub.at(graph.at(crr).front().to))
            std::swap(e, graph.at(crr).front());
        }
      })(root, root);
      size_t now = 0; head.at(root) = root;
      fix ([&](auto dfs, size_t crr, size_t p) -> void {
        ord.at(crr) = now, now++;
        for (auto const& e : graph.at(crr)) {
          if (e.to == p) continue;
          head.at(e.to) = (e.to == graph.at(crr).front().to
            ? head.at(crr) : e.to);
          dfs(e.to, crr);
        }
      })(root, root);
    }
    // Calculate the lowest common ancestor.
    auto lca (size_t u, size_t v) -> size_t {
      assert(built);
      while (head.at(u) != head.at(v)) {
        if (ord.at(u) > ord.at(v)) std::swap(u, v);
        v = prt.at(head.at(v));
      }
      return ord.at(u) < ord.at(v) ? u : v;
    }
};
int main() {
  std::cin.tie(0); std::cin.sync_with_stdio(false);
  size_t n, q; std::cin >> n >> q;
  auto hld = heavy_light_decomposition(n);
  struct edge_t {size_t to; int c, d;};
  std::vector<std::vector<edge_t>> graph(n);
  for (size_t i = 0; i < n - 1; i++) {
    size_t a, b; int c, d;
    std::cin >> a >> b >> c >> d;
    a--, b--;
    hld.insert(a, b);
    graph.at(a).push_back({b, c, d});
    graph.at(b).push_back({a, c, d});
  }
  int root = 0; hld.build(root);
  struct query_t {size_t id; int x, y, coeff;};
  std::vector<std::vector<query_t>> queries(n);
  for (size_t i = 0; i < q; i++) {
    int x, y, u, v;
    std::cin >> x >> y >> u >> v;
    u--, v--;
    queries.at(u).push_back({i, x, y, 1});
    queries.at(v).push_back({i, x, y, 1});
    queries.at(hld.lca(u, v)).push_back({i, x, y, -2});
  }
  std::vector<unsigned> cnt(n);
  std::vector<int> dst(n), ans(q);
  int depth = 0;
  auto advance = [&] (int c, int d, int coeff) {
    cnt.at(c) += coeff;
    dst.at(c) += d * coeff;
    depth     += d * coeff;
  };
  fix ([&](auto dfs, size_t crr, size_t prt) -> void {
    for (auto q : queries.at(crr)) {
      ans.at(q.id) += (depth - dst.at(q.x) + (cnt.at(q.x) * q.y)) * q.coeff;
    }
    for (auto const& e : graph.at(crr)) {
      if ((e.to) == prt) continue;
      advance(e.c, e.d, +1);
      dfs(e.to, crr);
      advance(e.c, e.d, -1);
    }
  })(root, root);
  std::for_each(ans.begin(), ans.end(), [](auto x){std::cout << x << std::endl;});
  return 0;
}

Measured memory_bytes: 39476