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(map[edge][2]int, n-1)
	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[edge{a, b}] = [2]int{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
		if u > v {
			u, v = v, u
		}
		col[v] = append(col[v], x)
		col[u] = append(col[u], x)
		p := lca.query(u, v)
		col[p] = append(col[p], x)
		qs[i] = query{x, y, u, v}
	}

	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(next, d int)
	dfs = func(next, d int) {
		for _, to := range g[next] {
			if dist[to] != 0 || to == 0 {
				continue
			}
			a, b := to, next
			if a > b {
				a, b = b, a
			}
			e := es[edge{a, b}]
			colDist[e[0]] += e[1]
			colNum[e[0]]++
			dist[to] = d + e[1]
			if len(col[to]) != 0 {
				vColCnt[to] = map[int]int{}
				vColDist[to] = map[int]int{}
			}
			for _, c := range col[to] {
				vColCnt[to][c] = colNum[c]
				vColDist[to][c] = colDist[c]
			}
			dfs(to, d+es[edge{a, b}][1])
			colDist[e[0]] -= e[1]
			colNum[e[0]]--
		}
	}

	dfs(0, 0)

	for i := 0; i < q; i++ {
		x, y, u, v := qs[i].x, qs[i].y, qs[i].u, qs[i].v
		p := lca.query(u, v)
		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 {
	a, b int
}

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

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

func LCAInit(g [][]int) LCA {
	n := len(g)
	res := LCA{make([]int, n), [32][]int{}}
	for i := 0; i < 32; i++ {
		res.par[i] = make([]int, n)
	}
	var dfs func(v, p, d int)
	dfs = func(v, p, d int) {
		res.par[0][v] = p
		res.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 < 31; i++ {
		for j := 0; j < n; j++ {
			if res.par[i][j] == -1 {
				res.par[i+1][j] = -1
			} else {
				res.par[i+1][j] = res.par[i][res.par[i][j]]
			}
		}
	}

	return res
}

func (lca LCA) query(u, v int) int {
	if lca.dep[u] > lca.dep[v] {
		u, v = v, u
	}
	for i := 31; 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 := 31; 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: 128128