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)
	g := make([][]int, 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})
		g[a] = append(g[a], b)
		g[b] = append(g[b], a)
	}

	lca := LCAInit(g)

	qs := make([]query, q)
	col := make([][]int, n)
	for i := 0; i < q; i++ {
		x, y, u, v := scanInt(), scanInt(), scanInt()-1, scanInt()-1
		p := lca.Query(u, v)
		col[v] = append(col[v], x)
		col[u] = append(col[u], x)
		col[p] = append(col[p], x)
		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(g [][]int) LCA {
	n := len(g)
	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 _, to := range g[v] {
			if to == p {
				continue
			}
			dfs(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]
}


Measured memory_bytes: 103808