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 Java8 (OpenJDK 1.8.0) (judge verdict: Runtime Error)

import java.util.*;
import java.io.*;

public class Main {
	static ArrayList<Route>[] tree;
	static Node[] nodes;
	public static void main (String[] args) throws Exception {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		String[] first = br.readLine().split(" ", 2);
		int n = Integer.parseInt(first[0]);
		int q = Integer.parseInt(first[1]);
		tree = new ArrayList[n];
		nodes = new Node[n];
		for (int i = 0; i < n; i++) {
			tree[i] = new ArrayList<Route>();
		}
		for (int i = 0; i < n - 1; i++) {
			String[] line = br.readLine().split(" ", 4);
			int a = Integer.parseInt(line[0]) - 1;
			int b = Integer.parseInt(line[1]) - 1;
			int c = Integer.parseInt(line[2]) - 1;
			int d = Integer.parseInt(line[3]);
			Route route = new Route(c, d, a, b);
			tree[a].add(route);
			tree[b].add(route);
		}
		addNode(0, new ArrayList<Integer>(), new int[n], new int[n], 0);
		StringBuilder sb = new StringBuilder();
		for (int i = 0; i < q; i++) {
			String[] line = br.readLine().split(" ", 4);
			int x = Integer.parseInt(line[0]) - 1;
			int y = Integer.parseInt(line[1]);
			int u = Integer.parseInt(line[2]) - 1;
			int v = Integer.parseInt(line[3]) - 1;
			int idx = 0;
			while (idx < nodes[u].fromRoot.size() && idx < nodes[v].fromRoot.size() && nodes[u].fromRoot.get(idx).equals(nodes[v].fromRoot.get(idx))) {
				idx++;
			}
			if (idx != 0) {
				idx--;
			}
			
			int total = nodes[u].total - nodes[u].colorSum[x] + nodes[u].colorNum[x] * y + nodes[v].total - nodes[v].colorSum[x] + nodes[v].colorNum[x] * y;
			total -= (nodes[idx].total - nodes[idx].colorSum[x] + nodes[idx].colorNum[x] * y) * 2;
			sb.append(total).append("\n");
		}
		System.out.print(sb);
	}
	
	static void addNode(int idx, ArrayList<Integer> fromRoot, int[] colorNum, int[] colorSum, int total) {
		nodes[idx] = new Node(fromRoot, colorNum, colorSum, total);
		for (Route r : tree[idx]) {
			int to;
			if (r.to == idx) {
				to = r.from;
			} else {
				to = r.to;
			}
			if (nodes[to] == null) {
				ArrayList<Integer> nextList = (ArrayList<Integer>)(fromRoot.clone());
				nextList.add(idx);
				int[] nextNum = (int[])(colorNum.clone());
				nextNum[r.color]++;
				int[] nextSum = (int[])(colorSum.clone());
				nextSum[r.color] += r.dist;
				addNode(to, nextList, nextNum, nextSum, total + r.dist);
			}
		}
	}
	
	
	static class Node {
		ArrayList<Integer> fromRoot;
		int[] colorNum;
		int[] colorSum;
		int total;
		
		public Node(ArrayList<Integer> fromRoot, int[] colorNum, int[] colorSum, int total) {
			this.fromRoot = fromRoot;
			this.colorNum = colorNum;
			this.colorSum = colorSum;
			this.total = total;
		}
	}
	
	static class Route {
		int color;
		int dist;
		int from;
		int to;
		
		public Route(int color, int dist, int from, int to) {
			this.color = color;
			this.dist = dist;
			this.from = from;
			this.to = to;
		}
		
		public boolean equals(Object o) {
			Route another = (Route) o;
			return this.color == another.color && this.dist == another.dist && ((this.from == another.from && this.to == another.to) || (this.from == another.to && this.to == another.from));
		}
	}
}