#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>

#include <iostream>
#include <complex>
#include <string>
#include <algorithm>
#include <numeric>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <unordered_map>
#include <unordered_set>

#include <functional>
#include <cassert>

typedef long long ll;
using namespace std;

#ifndef LOCAL
#define debug(x) ;
#else
#define debug(x) cerr << __LINE__ << " : " << #x << " = " << (x) << endl;

template <typename T1, typename T2>
ostream &operator<<(ostream &out, const pair<T1, T2> &p) {
  out << "{" << p.first << ", " << p.second << "}";
  return out;
}

template <typename T>
ostream &operator<<(ostream &out, const vector<T> &v) {
  out << '{';
  for (const T &item : v) out << item << ", ";
  out << "\b\b}";
  return out;
}
#endif

#define mod 1000000007 //1e9+7(prime number)
#define INF 1000000000 //1e9
#define LLINF 2000000000000000000LL //2e18
#define SIZE 200010

/*Lowest Common Ancstor*/
struct LCA {
  int n;
  vector<vector<int>> tree, parent;
  vector<int> depth;
  int log2n;

  LCA(int n): n(n), tree(n), depth(n, -1) {
    log2n = 0;
    for (log2n = 1; (1 << log2n) < n; log2n++)
      ;
    parent.assign(log2n, vector<int>(n, -1));
  }

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

  void dfs(int now, int p, int d) {
    parent[0][now] = p;
    depth[now] = d;

    for (int to : tree[now])
      if (to != p)
        dfs(to, now, d + 1);
  }

  void build(int root) {
    dfs(root, -1, 0);

    for (int i = 0; i < log2n - 1; i++)
      for (int j = 0; j < n; j++)
        parent[i + 1][j] = parent[i][j] == -1 ? -1 : parent[i][parent[i][j]];
  }

  int query(int a, int b) {
    if (depth[a] > depth[b]) swap(a, b);

    for (int i = 0; i < log2n; i++)
      if ((depth[b] - depth[a]) >> i & 1)
        b = parent[i][b];

    if (a == b) return a;

    for (int i = log2n - 1; i >= 0; i--) {
      if (parent[i][a] != parent[i][b]) {
        a = parent[i][a];
        b = parent[i][b];
      }
    }

    return parent[0][a];
  }
};

/* Binary Indexed Tree(0-index) */

template<typename Type = int>
struct BIT {
  int bit_size;
  vector<Type> data;

  BIT(int n) {
    bit_size = n;
    data.assign(n + 2, 0);
  }

  //add x to kth value
  void add(int k, Type x) {
    k++;
    while (k <= bit_size) {
      data[k] += x;
      k += k & (-k);
    }
  }

  //sum of [0,k)
  Type query(int k) {
    Type rec = 0;
    while (k > 0) {
      rec += data[k];
      k -= k & (-k);
    }
    return rec;
  }

  //sum of [a, b)
  Type query(int a, int b) {
    return query(b) - query(a);
  }
};

vector<pair<int,pair<int,int>>> G[SIZE];

int idx = 0;
int in[SIZE], out[SIZE], w[SIZE];
vector<int> ce[SIZE];

void dfs(int now, int back = -1) {
  in[now] = idx++;

  for (auto e : G[now]) {
    if (e.first == back) continue;
    dfs(e.first, now);
    w[e.first] = e.second.second;
    ce[e.second.first].push_back(e.first);
  }

  out[now] = idx++;
}

int main() {
  int N, Q;

  scanf("%d%d", &N, &Q);

  LCA lca(N);
  BIT<ll> bit(N * 2), bit2(N * 2);

  for (int i=0; i<N-1; i++) {
    int a, b, c, d;
    scanf("%d%d%d%d", &a, &b, &c, &d);
    a--; b--; c--;
    G[a].push_back({b, {c, d}});
    G[b].push_back({a, {c, d}});
    lca.add_edge(a, b);
  }

  dfs(0);
  lca.build(0);

  for (int i=0; i<N; i++) {
    bit.add(in[i], -w[i]);
    bit.add(out[i], w[i]);
  }

  int x[SIZE], y[SIZE], u[SIZE], v[SIZE];
  ll ans[SIZE];

  pair<int,int> query[SIZE];

  for (int i=0; i<Q; i++) {
    scanf("%d%d%d%d", x+i, y+i, u+i, v+i);
    x[i]--; u[i]--; v[i]--;
    query[i] = {x[i], i};
  }

  sort(query, query+Q);

  for (int i=0; i<Q; i++) {
    if (i == 0 || query[i-1].first != query[i].first) {
      for (int j : ce[query[i].first]) {
        bit.add(in[j], w[j]);
        bit.add(out[j], -w[j]);
        bit2.add(in[j], -1);
        bit2.add(out[j], 1);
      }
    }

    int idx = query[i].second;

    int g = lca.query(u[idx], v[idx]);

    ll sum = bit.query(out[u[idx]], out[g]) + bit.query(out[v[idx]], out[g]);
    ll count = bit2.query(out[u[idx]], out[g]) + bit2.query(out[v[idx]], out[g]);

    ans[idx] = sum + count * y[idx];

    if (i < Q - 1 && query[i].first != query[i+1].first) {
      for (int j : ce[query[i].first]) {
        bit.add(in[j], -w[j]);
        bit.add(out[j], w[j]);
        bit2.add(in[j], 1);
        bit2.add(out[j], -1);
      }
    }
  }

  for (int i=0; i<Q; i++) {
    printf("%lld\n", ans[i]);
  }

  return 0;
}


Measured memory_bytes: 43000