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: Runtime Error)

/**
 * code generated by JHelper
 * More info: https://github.com/AlexeyDmitriev/JHelper
 * @author tatsumack
 */

#include <iostream>
#include <fstream>

#include <iostream>
#include <limits.h>
#include <algorithm>
#include <bitset>
#include <cctype>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <deque>
#include <functional>
#include <iomanip>

#include <list>
#include <map>
#include <numeric>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <utility>
#include <vector>
#include <queue>
#include <unordered_map>
#include <unordered_set>

#define int long long
#define REP(i, n) for (int i = 0, i##_len = (n); i < i##_len; ++i)
#define REPS(i, n) for (int i = 1, i##_len = (n); i <= i##_len; ++i)
#define FOR(i, a, b) for (int i = (a), i##_len = (b); i <= i##_len; ++i)
#define REV(i, a, b) for (int i = (a); i >= (b); --i)
#define CLR(a, b) memset((a), (b), sizeof(a))
#define DUMP(x) cout << #x << " = " << (x) << endl;
#define INF 1001001001001001001ll
#define fcout cout << fixed << setprecision(12)

using namespace std;

typedef pair<int, int> P;

struct LCA {
    static const int MAX_V = 100100;
    static const int MAX_LOG_V = 21;

    vector<vector<int>> G;
    vector<vector<int>> parent;
    vector<int> depth;

    LCA(int size) {
        G = vector<vector<int>>(size);
        parent = vector<vector<int>>(MAX_LOG_V, vector<int>(size));
        depth = vector<int>(size);
    }


    void dfs(int v, int p, int d) {
        parent[0][v] = p;
        depth[v] = d;
        for (int i = 0; i < G[v].size(); i++) {
            if (G[v][i] != p) dfs(G[v][i], v, d + 1);
        }
    }

    void init(int root, int V) {
        dfs(root, -1, 0);
        for (int k = 0; k + 1 < MAX_LOG_V; k++) {
            for (int v = 0; v < V; v++) {
                if (parent[k][v] < 0)
                    parent[k + 1][v] = -1;
                else
                    parent[k + 1][v] = parent[k][parent[k][v]];
            }
        }
    }

    int get(int u, int v) {
        if (depth[u] > depth[v]) swap(u, v);
        for (int k = 0; k < MAX_LOG_V; k++) {
            if ((depth[v] - depth[u]) >> k & 1) {
                v = parent[k][v];
            }
        }
        if (u == v) return u;

        for (int k = MAX_LOG_V - 1; k >= 0; k--) {
            if (parent[k][u] != parent[k][v]) {
                u = parent[k][u];
                v = parent[k][v];
            }
        }

        return parent[0][u];
    }
};

class FColorfulTree {
public:
    static constexpr int kStressIterations = 0;

    static void generateTest(std::ostream& test) {
    }

    vector<vector<vector<int>>> G;
    vector<int> dist, X, Y, U, V, L, cnum, csum;
    vector<vector<int>> C;
    vector<vector<int>> num;
    vector<vector<int>> sum;

    void dfs(int v, int p = -1) {
        for (auto c : C[v]) {
            num[v][c] = cnum[c];
            sum[v][c] = csum[c];
        }

        REP(i, G[v].size()) {
            int to = G[v][i][0];
            int c = G[v][i][1];
            int d = G[v][i][2];
            if (to == p) continue;

            dist[to] = dist[v] + d;

            cnum[c]++;
            csum[c] += d;
            dfs(to, v);
            cnum[c]--;
            csum[c] -= d;
        }
    }

    void solve(std::istream& cin, std::ostream& cout) {
        int N, Q;
        cin >> N >> Q;

        dist.resize(N);
        LCA lca(N);

        G.resize(N);
        REP(i, N - 1) {
            int a, b, c, d;
            cin >> a >> b >> c >> d;
            a--, b--, c--;
            G[a].push_back({b, c, d});
            G[b].push_back({a, c, d});
            lca.G[a].push_back(b);
            lca.G[b].push_back(a);
        }
        lca.init(0, N);

        C.resize(N);
        cnum.resize(N);
        csum.resize(N);
        X.resize(Q);
        Y.resize(Q);
        U.resize(Q);
        V.resize(Q);
        L.resize(Q);
        num = vector<vector<int>>(N, vector<int>(N));
        sum = vector<vector<int>>(N, vector<int>(N));
        REP(i, Q) {
            int x, y, u, v;
            cin >> x >> y >> u >> v;
            x--, u--, v--;
            X[i] = x;
            Y[i] = y;
            U[i] = u;
            V[i] = v;
            int l = lca.get(u, v);
            L[i] = l;
            C[l].push_back(x);
            C[u].push_back(x);
            C[v].push_back(x);
        }

        dfs(0);

        REP(i, Q) {
            int u = U[i];
            int v = V[i];
            int l = L[i];
            int x = X[i];
            int d = dist[u] + dist[v] - 2 * dist[l];
            int n = num[u][x] + num[v][x] - 2 * num[l][x];
            int s = sum[u][x] + sum[v][x] - 2 * sum[l][x];
            cout << d - s + n * Y[i] << endl;
        }


    }
};


signed main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);
    std::istream& in(std::cin);
    std::ostream& out(std::cout);

    FColorfulTree solver;
    solver.solve(in, out);
    return 0;
}