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)

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

ostream& operator<<(ostream &out, string str) {
	for(char c : str) cout << c;
	return out;
}

template<class L, class R> ostream& operator<<(ostream &out, pair<L, R> p) {
	return out << "(" << p.first << ", " << p.second << ")";
}

template<class T> auto operator<<(ostream &out, T a) -> decltype(a.begin(), out) {
	out << "{";
	for(auto it = a.begin(); it != a.end(); it = next(it))
		out << (it != a.begin() ? ", " : "") << *it;
	return out << "}";
}

void dump() { cerr << "\n"; }
template<class T, class... Ts> void dump(T a, Ts... x) {
	cerr << a << ", ";
	dump(x...);
}

#ifdef DEBUG
#  define debug(...) cerr << "[" #__VA_ARGS__ "]: ", dump(__VA_ARGS__)
#else
#  define debug(...) false
#endif

#define REP(i, n) for(int i = 0; i < n; i++)
#define FOR(i, a, b) for(int i = a; i <= b; i++)
#define ST first
#define ND second

template<class T> int size(T && a) {
	return a.size();
}

using LL = long long;
using PII = pair<int, int>;

struct edge {
	int to, col, len;
};

vector<vector<edge>> graph;
vector<int> par, dist;
vector<int> pre, pos;

int t = 0;
void set_par(int v = 0, int p = -1) {
	pre[v] = t++;
	par[v] = p;
	for(edge &e : graph[v]) 
	{
		int u = e.to;
		int d = e.len;
		if(u != p) {
			dist[u] = dist[v] + d;
			set_par(u, v);
		}
	}
	pos[v] = t++;
}

bool is_par(int v, int u) {
	return pre[v] <= pre[u] && pos[u] <= pos[v];
}

vector<vector<int>> jump;
int LCA(int v, int u) {
	if(is_par(v, u)) return v;
	if(is_par(u, v)) return u;

	for(int i = 19; i > 0; i--) {
		if(jump[i][v] != -1 && !is_par(jump[i][v], u))
			v = jump[i][v];
	}

	return jump[0][v];
}

vector<vector<PII>> dists;
void dist_dfs(int c, int v = 0) {
	for(edge &e : graph[v]) {
		int u = e.to;
		int d = e.len;
		int col = e.col;
		if(u != par[v]) {
			dists[c][u] = dists[c][v];
			if(col == c) dists[c][u].ND++;
			else dists[c][u].ST += d;
			dist_dfs(c, u);
		}
	}
}

int main() {
	ios_base::sync_with_stdio(0);
	cin.tie(0);

	int n, q;
	cin >> n >> q;

	struct just_edge {
		int a, b, d;
	};

	vector<vector<just_edge>> edges(n - 1);
	vector<int> color_cnt(n - 1);
	graph.resize(n);
	REP(i, n - 1) {
		int a, b, c, d;
		cin >> a >> b >> c >> d;
		a--, b--, c--;
		color_cnt[c]++;
		graph[a].emplace_back(edge{b, c, d});
		graph[b].emplace_back(edge{a, c, d});
		edges[c].emplace_back(just_edge{a, b, d});
	}
	
	par.resize(n);
	dist.resize(n);
	pre.resize(n);
	pos.resize(n);
	set_par();

	int log = 20;
	jump.resize(20, vector<int>(n));
	jump[0] = par;

	FOR(i, 1, log - 1) {
		REP(j, n)
			jump[i][j] = (jump[i - 1][j] == -1 ? -1 : jump[i - 1][jump[i - 1][j]]);
	}

	int S = 400;
	REP(i, n - 1) {
		if(color_cnt[i] >= S) {
			dists[i].resize(n);
			dist_dfs(i);
		}
	}

	auto add = [&](PII a, PII b) -> PII {
		return {a.ST + b.ST, a.ND + b.ND};
	};

	auto rem = [&](PII a, PII b) -> PII {
		return {a.ST - b.ST, a.ND - b.ND};
	};

	REP(i, q) {
		int x, y, u, v;
		cin >> x >> y >> u >> v;
		x--, u--, v--;

		if(color_cnt[x] >= S) {
			int lca = LCA(u, v);
			PII ret = add(dists[x][u], dists[x][v]);
			ret = rem(ret, add(dists[x][lca], dists[x][lca]));
			cout << ret.ST + ret.ND * y << "\n";
		}
		else {
			int lca = LCA(u, v);
			int ret = dist[u] + dist[v] - dist[lca] * 2;
			for(auto &e : edges[x]) {
				int a = e.a;
				int b = e.b;
				int d = e.d;
				if(is_par(a, b)) swap(a, b);
				if(!is_par(a, lca) && (is_par(a, u) || is_par(a, v)))
					ret += y - d;
			}
			cout << ret << "\n";
		}
	}
}