Problem:
Score : 600 points

Problem Statement

There is a tree with N vertices numbered 1 to N.
The i-th edge in this tree connects Vertex a_i and Vertex b_i, and the color and length of that edge are c_i and d_i, respectively.
Here the color of each edge is represented by an integer between 1 and N-1 (inclusive). The same integer corresponds to the same color, and different integers correspond to different colors.

Answer the following Q queries:

Query j (1 \leq j \leq Q): assuming that the length of every edge whose color is x_j is changed to y_j, find the distance between Vertex u_j and Vertex v_j. (The changes of the lengths of edges do not affect the subsequent queries.)

Constraints

2 \leq N \leq 10^5

1 \leq Q \leq 10^5

1 \leq a_i, b_i \leq N

1 \leq c_i \leq N-1

1 \leq d_i \leq 10^4

1 \leq x_j \leq N-1

1 \leq y_j \leq 10^4

1 \leq u_j < v_j \leq N

The given graph is a tree.

All values in input are integers.

Input

Input is given from Standard Input in the following format:

N Q
a_1 b_1 c_1 d_1
:
a_{N-1} b_{N-1} c_{N-1} d_{N-1}
x_1 y_1 u_1 v_1
:
x_Q y_Q u_Q v_Q

Output

Print Q lines. The j-th line (1 \leq j \leq Q) should contain the answer to Query j.

Sample Input 1

5 3
1 2 1 10
1 3 2 20
2 4 4 30
5 2 1 40
1 100 1 4
1 100 1 5
3 1000 3 4

Sample Output 1

130
200
60

The graph in this input is as follows:

Here the edges of Color 1 are shown as solid red lines, the edge of Color 2 is shown as a bold green line, and the edge of Color 4 is shown as a blue dashed line.

Query 1: Assuming that the length of every edge whose color is 1 is changed to 100, the distance between Vertex 1 and Vertex 4 is 100 + 30 = 130.

Query 2: Assuming that the length of every edge whose color is 1 is changed to 100, the distance between Vertex 1 and Vertex 5 is 100 + 100 = 200.

Query 3: Assuming that the length of every edge whose color is 3 is changed to 1000 (there is no such edge), the distance between Vertex 3 and Vertex 4 is 20 + 10 + 30 = 60. Note that the edges of Color 1 now have their original lengths.

Solution in C++14 (GCC 5.4.1) (judge verdict: Accepted)

#define _USE_MATH_DEFINES
#include <bits/stdc++.h>
using namespace std;
/////////////////////////////////////////////////////////////////////////
// LCA
/////////////////////////////////////////////////////////////////////////
class LowestCommonAncestor {
public:
  LowestCommonAncestor();
  LowestCommonAncestor(const vector<vector<int>>& g, int r);
  LowestCommonAncestor(const vector<int> g[], int r, int siz);
  void build(const vector<vector<int>>& g, int r);
  void build(const vector<int> g[], int r, int siz);
  int get(int u, int v) const;
  int getParent(int cur, int u) const;
  int getDepth(int cur) const;
private:
  void initialize();
  void dfs(int cur, int par, int d);
  static constexpr int MAX_SIZE = 30;
  vector<vector<int>> graph;
  vector<vector<int>> parent;
  vector<int> depth;
  int bit_;
  int root;
};

LowestCommonAncestor::LowestCommonAncestor() {};
LowestCommonAncestor::LowestCommonAncestor(const vector<vector<int>>& g, int r = -1) 
: graph(g), root(r) {
  if (root == -1) root = 0;
  initialize();
}
LowestCommonAncestor::LowestCommonAncestor(const vector<int> g[], int r = -1, int siz = -1) 
: root(r) {
  assert(siz > 0);
  if (root == -1) root = 0;
  graph.resize(siz);
  for (int i = 0; i < siz; i++) for (auto& j : g[i]) graph[i].push_back(j);
  initialize();
}
void LowestCommonAncestor::build(const vector<vector<int>>& g, int r = -1) {
  root = r;
  graph = g;
  if (root == -1) root = 0;
  initialize();
}
void LowestCommonAncestor::build(const vector<int> g[], int r = -1, int siz = -1) {
  assert(siz > 0);
  root = r;
  graph.resize(siz);
  for (int i = 0; i < siz; i++) for (auto& j : g[i]) graph[i].push_back(j);
  initialize();
}
int LowestCommonAncestor::get(int u, int v) const {
  assert(u >= 0 && u < (int) graph.size());
  assert(v >= 0 && v < (int) graph.size());
  if (depth[u] > depth[v]) swap(u, v);
  for (int i = 0; i < bit_; ++i) if (((depth[v] - depth[u]) >> i) & 1) v = parent[v][i];
  if (u == v) return u;
  for (int i = bit_ - 1; i >= 0; --i) if (parent[u][i] != parent[v][i]) u = parent[u][i], v = parent[v][i];
  return parent[u][0];
}
int LowestCommonAncestor::getParent(int cur, int u = 0) const {
  assert(cur >= 0 && cur < (int) graph.size());
  assert(u >= 0 && (int) graph[cur].size() > u);
  return parent[cur][u];
}
int LowestCommonAncestor::getDepth(int cur) const {
  assert(cur >= 0 && cur < (int) depth.size());
  return depth[cur];
}
void LowestCommonAncestor::initialize() {
  bit_ = 1;
  while ((1 << bit_) < (int) graph.size()) ++bit_;
  parent = vector<vector<int>>((int) graph.size(), vector<int>(bit_));
  depth.assign((int) graph.size(), -1);
  dfs(root, -1, 0);
  for (int i = 0; i < bit_ - 1; ++i) {
    for (int v = 0; v < (int) graph.size(); ++v) {
      if (depth[v] == -1) continue;
      if (parent[v][i] < 0) parent[v][i + 1] = -1;
      else parent[v][i + 1] = parent[parent[v][i]][i];
    }
  }
}
void LowestCommonAncestor::dfs(int cur, int par, int d) {
  parent[cur][0] = par;
  depth[cur] = d;
  for (auto& child : graph[cur]) if (child != par) dfs(child, cur, d + 1);
}
using LCA = LowestCommonAncestor;
/////////////////////////////////////////////////////////////////////////
// END LCA
/////////////////////////////////////////////////////////////////////////
int n;
vector<vector<int>> g1[101010];
vector<int> g2[101010];
vector<int> need[101010];
map<int, int> res_cnt[101010], res_sum[101010];
int dist[101010];
int col_cnt[101010], col_sum[101010];
void dfs(int cur, int par) {
  for (int c : need[cur]) {
    res_cnt[cur][c] = col_cnt[c];
    res_sum[cur][c] = col_sum[c];
  }
  for (auto nxt: g1[cur]) {
    int child = nxt[0];
    int c = nxt[1];
    int d = nxt[2];
    if (child == par) continue;
    dist[child] = dist[cur] + d;
    col_cnt[c]++;
    col_sum[c] += d;
    dfs(child, cur);
    col_cnt[c]--;
    col_sum[c] -= d;
  }
}
signed main() { 
  ios::sync_with_stdio(false); cin.tie(0);
  int q;
  cin >> n >> q;
  for (int i = 0; i + 1 < n; i++) {
    int a, b, c, d;
    cin >> a >> b >> c >> d;
    a--;
    b--;
    c--;
    g1[a].push_back({b, c, d});
    g1[b].push_back({a, c, d});
    g2[a].push_back(b);
    g2[b].push_back(a);
  }
  LCA lca(g2, 0, 101010);
  vector<int> inx(q), iny(q), inu(q), inv(q), inw(q);
  for (int i = 0; i < q; i++) {
    cin >> inx[i] >> iny[i] >> inu[i] >> inv[i];
    inx[i]--;
    inu[i]--;
    inv[i]--;
    inw[i] = lca.get(inu[i], inv[i]);
    need[inu[i]].push_back(inx[i]);
    need[inv[i]].push_back(inx[i]);
    need[inw[i]].push_back(inx[i]);
  }
  dfs(0, -1);
  for (int i = 0; i < q; i++) {
    int du = dist[inu[i]] - res_sum[inu[i]][inx[i]] + res_cnt[inu[i]][inx[i]] * iny[i];
    int dv = dist[inv[i]] - res_sum[inv[i]][inx[i]] + res_cnt[inv[i]][inx[i]] * iny[i];
    int dw = dist[inw[i]] - res_sum[inw[i]][inx[i]] + res_cnt[inw[i]][inx[i]] * iny[i];
    cout << du + dv - 2 * dw << '\n';
  }
  return 0;
}