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 Rust (1.15.1) (judge verdict: Accepted)

use std::collections::{BTreeMap, BTreeSet, VecDeque};

const INF: u64 = 1 << 60;

fn main() {
    let (r, w) = (std::io::stdin(), std::io::stdout());
    let mut sc = IO::new(r.lock(), w.lock());
    let n: usize = sc.read();
    let q: usize = sc.read();
    let mut graph = vec![vec![]; n];
    let mut simple = vec![vec![]; n];
    for _ in 1..n {
        let a = sc.read::<usize>() - 1;
        let b = sc.read::<usize>() - 1;
        let c = sc.read::<usize>() - 1;
        let d: u64 = sc.read();

        graph[a].push((b, c, d));
        graph[b].push((a, c, d));

        simple[a].push(b);
        simple[b].push(a);
    }

    let lca = lca::LowestCommonAncestor::new(&simple);
    let mut dist = vec![INF; n];
    dist[0] = 0;
    let mut queue = VecDeque::new();
    queue.push_back(0);
    while let Some(v) = queue.pop_front() {
        for &(next, _, cost) in graph[v].iter() {
            if dist[next] > dist[v] + cost {
                queue.push_back(next);
                dist[next] = dist[v] + cost;
            }
        }
    }

    let mut queries = vec![];
    let mut marker = vec![vec![]; n];
    for _ in 0..q {
        let c = sc.read::<usize>() - 1;
        let d: u64 = sc.read();
        let u = sc.read::<usize>() - 1;
        let v = sc.read::<usize>() - 1;
        let lca = lca.get_lca(u, v);
        marker[u].push(c);
        marker[v].push(c);
        marker[lca].push(c);

        queries.push((c, d, u, v, lca));
    }

    let mut color_count = vec![BTreeMap::new(); n];
    let mut color_dist = vec![BTreeMap::new(); n];

    euler_tour(
        0,
        0,
        &graph,
        &mut color_count,
        &mut color_dist,
        &mut vec![0; n],
        &mut vec![0; n],
        &marker,
    );
    for (c, d, u, v, lca) in queries.into_iter() {
        let total_dist = dist[u] + dist[v] - 2 * dist[lca];
        let color_dist = color_dist[u][&c] + color_dist[v][&c] - 2 * color_dist[lca][&c];
        let color_count = color_count[u][&c] + color_count[v][&c] - 2 * color_count[lca][&c];

        let ans = total_dist - color_dist + (color_count as u64) * d;
        sc.write(ans.to_string());
        sc.write("\n");
    }
}

fn euler_tour(
    v: usize,
    p: usize,
    graph: &Vec<Vec<(usize, usize, u64)>>,
    color_count: &mut Vec<BTreeMap<usize, usize>>,
    color_dist: &mut Vec<BTreeMap<usize, u64>>,
    cur_color_count: &mut Vec<usize>,
    cur_color_dist: &mut Vec<u64>,
    marker: &Vec<Vec<usize>>,
) {
    for &color in marker[v].iter() {
        color_count[v].insert(color, cur_color_count[color]);
        color_dist[v].insert(color, cur_color_dist[color]);
    }

    for &(next, color, cost) in graph[v].iter() {
        if next == p {
            continue;
        }
        cur_color_count[color] += 1;
        cur_color_dist[color] += cost;
        euler_tour(
            next,
            v,
            graph,
            color_count,
            color_dist,
            cur_color_count,
            cur_color_dist,
            marker,
        );
        cur_color_dist[color] -= cost;
        cur_color_count[color] -= 1;
    }
}

pub mod lca {
    const MAX_PARENT: usize = 1 << 50;
    pub struct LowestCommonAncestor {
        parent: Vec<Vec<usize>>,
        depth: Vec<usize>,
        log_v: usize,
    }

    impl LowestCommonAncestor {
        pub fn new(graph: &Vec<Vec<usize>>) -> Self {
            let num_v = graph.len();
            let root = 0;
            let mut depth = vec![0; num_v];

            let mut log_v = 1;
            let mut i = 1;
            while i <= num_v {
                i *= 2;
                log_v += 1;
            }
            let mut parent: Vec<Vec<usize>> = vec![vec![0; num_v]; log_v];

            let mut depth_vis = vec![false; num_v];
            let mut stack = ::std::collections::VecDeque::new();
            stack.push_front(root);
            parent[0][root] = MAX_PARENT;
            depth[root] = 0;
            depth_vis[root] = true;
            while !stack.is_empty() {
                let v = stack.pop_front().unwrap();
                stack.push_front(v);
                for &u in &graph[v] {
                    if depth_vis[u] {
                        continue;
                    }
                    parent[0][u] = v;
                    depth[u] = depth[v] + 1;
                    depth_vis[u] = true;
                    stack.push_front(u);
                }

                let head = stack.pop_front().unwrap();
                if head != v {
                    stack.push_front(head);
                }
            }

            for k in 0..(log_v - 1) {
                for u in 0..num_v {
                    parent[k + 1][u] = if parent[k][u] == MAX_PARENT {
                        MAX_PARENT
                    } else {
                        parent[k][parent[k][u]]
                    };
                }
            }

            LowestCommonAncestor {
                parent: parent,
                depth: depth,
                log_v: log_v,
            }
        }

        pub fn get_lca(&self, u: usize, v: usize) -> usize {
            let (mut u, mut v) = if self.depth[u] <= self.depth[v] {
                (u, v)
            } else {
                (v, u)
            };
            for k in 0..self.log_v {
                if ((self.depth[v] - self.depth[u]) & (1 << k)) != 0 {
                    v = self.parent[k][v];
                }
            }
            if u == v {
                return u;
            }

            for k in (0..self.log_v).rev() {
                if self.parent[k][u] != self.parent[k][v] {
                    u = self.parent[k][u];
                    v = self.parent[k][v];
                }
            }
            return self.parent[0][u];
        }

        pub fn get_dist(&self, u: usize, v: usize) -> usize {
            let lca = self.get_lca(u, v);
            self.depth[u] + self.depth[v] - self.depth[lca] * 2
        }
    }
}

pub struct IO<R, W: std::io::Write>(R, std::io::BufWriter<W>);

impl<R: std::io::Read, W: std::io::Write> IO<R, W> {
    pub fn new(r: R, w: W) -> IO<R, W> {
        IO(r, std::io::BufWriter::new(w))
    }
    pub fn write<S: std::ops::Deref<Target = str>>(&mut self, s: S) {
        use std::io::Write;
        self.1.write(s.as_bytes()).unwrap();
    }
    pub fn read<T: std::str::FromStr>(&mut self) -> T {
        use std::io::Read;
        let buf = self
            .0
            .by_ref()
            .bytes()
            .map(|b| b.unwrap())
            .skip_while(|&b| b == b' ' || b == b'\n' || b == b'\r' || b == b'\t')
            .take_while(|&b| b != b' ' && b != b'\n' && b != b'\r' && b != b'\t')
            .collect::<Vec<_>>();
        unsafe { std::str::from_utf8_unchecked(&buf) }
            .parse()
            .ok()
            .expect("Parse error.")
    }
    pub fn vec<T: std::str::FromStr>(&mut self, n: usize) -> Vec<T> {
        (0..n).map(|_| self.read()).collect()
    }
    pub fn chars(&mut self) -> Vec<char> {
        self.read::<String>().chars().collect()
    }
}