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 Go (1.6) (judge verdict: Accepted)

package main

import (
	"bufio"
	"fmt"
	"os"
	"strconv"
)

var sc, wr = bufio.NewScanner(os.Stdin), bufio.NewWriter(os.Stdout)

func scanString() string   { sc.Scan(); return sc.Text() }
func scanRunes() []rune    { return []rune(scanString()) }
func scanInt() int         { a, _ := strconv.Atoi(scanString()); return a }
func scanInt64() int64     { a, _ := strconv.ParseInt(scanString(), 10, 64); return a }
func scanFloat64() float64 { a, _ := strconv.ParseFloat(scanString(), 64); return a }

func scanInts(n int) []int {
	res := make([]int, n)
	for i := 0; i < n; i++ {
		res[i] = scanInt()
	}
	return res
}

func debug(a ...interface{}) { fmt.Fprintln(os.Stderr, a...) }

func abs(a int) int {
	if a < 0 {
		return -a
	}
	return a
}
func min(a, b int) int {
	if a < b {
		return a
	}
	return b
}
func max(a, b int) int {
	if a > b {
		return a
	}
	return b
}

//•*¨*•.¸¸♪main•*¨*•.¸¸♪(　-ω-)ノ　(　・ω・)
func main() {
	defer wr.Flush()
	sc.Split(bufio.ScanWords)
	sc.Buffer(make([]byte, 10000), 1001001)

	n := scanInt()
	q := scanInt()

	es := make([][]edge, n)
	for i := 0; i < n-1; i++ {
		a, b, c, d := scanInt()-1, scanInt()-1, scanInt(), scanInt()
		if a > b {
			a, b = b, a
		}
		es[a] = append(es[a], edge{b, c, d})
		es[b] = append(es[b], edge{a, c, d})
	}

	lca := LCAInit(es)

	qs := make([]query, q)
	col := make([]map[int]bool, n)
	for i := 0; i < n; i++ {
		col[i] = map[int]bool{}
	}
	for i := 0; i < q; i++ {
		x, y, u, v := scanInt(), scanInt(), scanInt()-1, scanInt()-1
		p := lca.Query(u, v)
		col[u][x] = true
		col[v][x] = true
		col[p][x] = true
		qs[i] = query{x, y, u, v, p}
	}

	vColCnt := make([]map[int]int, n)
	vColDist := make([]map[int]int, n)
	dist := make([]int, n)
	colDist := map[int]int{}
	colNum := map[int]int{}

	var dfs func(v, p, d int)
	dfs = func(v, p, d int) {
		for _, e := range es[v] {
			if e.to == p {
				continue
			}
			a, b := e.to, v
			if a > b {
				a, b = b, a
			}

			colDist[e.c] += e.d
			colNum[e.c]++
			dist[e.to] = d + e.d

			if len(col[e.to]) != 0 {
				vColCnt[e.to] = map[int]int{}
				vColDist[e.to] = map[int]int{}
			}
			for c := range col[e.to] {
				vColCnt[e.to][c] = colNum[c]
				vColDist[e.to][c] = colDist[c]
			}

			dfs(e.to, v, dist[e.to])
			colDist[e.c] -= e.d
			colNum[e.c]--
		}
	}

	dfs(0, -1, 0)

	for i := 0; i < q; i++ {
		x, y, u, v, p := qs[i].x, qs[i].y, qs[i].u, qs[i].v, qs[i].p
		d := dist[u] + dist[v] - 2*dist[p]
		c := vColCnt[u][x]*y + vColCnt[v][x]*y - 2*vColCnt[p][x]*y - (vColDist[u][x] + vColDist[v][x] - 2*vColDist[p][x])
		fmt.Fprintln(wr, d+c)
	}
}

type edge struct {
	to, c, d int
}

type query struct {
	x, y, u, v, p int
}

// LCA struct
type LCA struct {
	dep []int
	par [][]int
}

// LCAInit function
func LCAInit(es [][]edge) LCA {
	n := len(es)
	k := 1
	for 1<<uint(k) < n {
		k++
	}
	lca := LCA{make([]int, n), make([][]int, k)}
	for i := 0; i < k; i++ {
		lca.par[i] = make([]int, n)
	}
	var dfs func(v, p, d int)
	dfs = func(v, p, d int) {
		lca.par[0][v] = p
		lca.dep[v] = d
		d++
		for _, e := range es[v] {
			if e.to == p {
				continue
			}
			dfs(e.to, v, d)
		}
	}
	dfs(0, -1, 0)
	for i := 0; i < len(lca.par)-1; i++ {
		for j := 0; j < n; j++ {
			if lca.par[i][j] == -1 {
				lca.par[i+1][j] = -1
			} else {
				lca.par[i+1][j] = lca.par[i][lca.par[i][j]]
			}
		}
	}

	return lca
}

// Query function for LCA
func (lca LCA) Query(u, v int) int {
	if lca.dep[u] > lca.dep[v] {
		u, v = v, u
	}
	for i := len(lca.par) - 1; i >= 0; i-- {
		if (lca.dep[v]-lca.dep[u])>>uint(i)&1 == 1 {
			v = lca.par[i][v]
		}
	}
	if u == v {
		return u
	}

	for i := len(lca.par) - 1; i >= 0; i-- {
		if lca.par[i][u] != lca.par[i][v] {
			u = lca.par[i][u]
			v = lca.par[i][v]
		}
	}
	return lca.par[0][u]
}