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.*;

public class Main {
    public static void main(String[] args) {
        new Main();
    }

    public Main(){
        Scanner sc = new Scanner(System.in);

        String[] NQ = sc.nextLine().split(" ");
        int N = Integer.parseInt(NQ[0]);
        int Q = Integer.parseInt(NQ[1]);

        Cell[] cells = new Cell[N + 1];
        String[] abcd;
        int a, b, c, d;
        Cell ac, bc;
        Node node;
        for (int i = 1; i <= N - 1; ++i) {
            abcd = sc.nextLine().split(" ");
            a = Integer.parseInt(abcd[0]);
            b = Integer.parseInt(abcd[1]);
            c = Integer.parseInt(abcd[2]);
            d = Integer.parseInt(abcd[3]);

            if (cells[a] == null) {
                cells[a] = new Cell(a);
            }

            if (cells[b] == null) {
                cells[b] = new Cell(b);
            }

            ac = cells[a];
            bc = cells[b];

            node = new Node(ac, bc, c, d);
            ac.connect(node);
            bc.connect(node);
        }

        int x, y, u, v;
        Cell uc;
        String[] xyuv;
        for (int j = 1; j <= Q; ++j) {
            xyuv = sc.nextLine().split(" ");
            x = Integer.parseInt(xyuv[0]);
            y = Integer.parseInt(xyuv[1]);
            u = Integer.parseInt(xyuv[2]);
            v = Integer.parseInt(xyuv[3]);
            uc = cells[u];
            System.out.println(search(uc, new int[N], v, x, y, 0));
        }

        sc.close();
    }

    public static final int FAILED = -1;

  public static int search(Cell now, int[] counted, int target, int x, int y, int total){
    if(now.getNum() == target){
      return total;
    }
    
    if(counted[now.getNum()] == FAILED){
      return FAILED;
    }
    
    //keep
    int[] _counted = counted.clone();
    int _total = total;
    int s = 0;
    int count = now.getNodeCount();
    for(int nodeIndex = 0; nodeIndex < count; nodeIndex++){
      Node node = now.getNode(nodeIndex);
      Cell next = node.getTheOther(now);
    
      counted[now.getNum()] = FAILED;
    
      total += node.getColor() == x ? y : node.getDistance();
      if((s = search(next, counted, target, x, y, total)) != FAILED){
        return s;
      }else{
        counted = _counted.clone();
        total = _total;
        continue;
      } 
    }

    return FAILED;
  }

    private class Node {
        private Cell a, b;
        private int color, distance;

        public Node(Cell a, Cell b, int color, int distance) {
            this.a = a;
            this.b = b;
            this.color = color;
            this.distance = distance;
        }

        public Cell getTheOther(Cell c) {
            if (a.getNum() == c.getNum()) {
                return this.b;
            } else if (b.getNum() == c.getNum()) {
                return this.a;
            }
            return null;
        }

        public int getColor() {
            return this.color;
        }

        public int getDistance() {
            return this.distance;
        }
    }

    private class Cell {
        private ArrayList<Node> connected = new ArrayList<Node>();
        private int num;

        public Cell(int num) {
            this.num = num;
        }

        public void connect(Node node) {
            connected.add(node);
        }

        public Node getNode(int index) {
            return this.connected.get(index);
        }

        public int getNum() {
            return this.num;
        }

        public int getNodeCount() {
            return this.connected.size();
        }
    }
}