macro_rules ! input { ( source = $ s : expr , $ ( $ r : tt ) * ) => { let mut iter = $ s . split_whitespace ( ) ; input_inner ! { iter , $ ( $ r ) * } } ; ( iter = $ iter : ident , $ ( $ r : tt ) * ) => { let s = { use std :: io :: Read ; let mut s = String :: new ( ) ; std :: io :: stdin ( ) . read_to_string ( & mut s ) . unwrap ( ) ; s } ; let mut $ iter = s . split_whitespace ( ) ; input_inner ! { $ iter , $ ( $ r ) * } } ; ( $ ( $ r : tt ) * ) => { let s = { use std :: io :: Read ; let mut s = String :: new ( ) ; std :: io :: stdin ( ) . read_to_string ( & mut s ) . unwrap ( ) ; s } ; let mut iter = s . split_whitespace ( ) ; input_inner ! { iter , $ ( $ r ) * } } ; }
macro_rules ! input_inner { ( $ iter : expr ) => { } ; ( $ iter : expr , ) => { } ; ( $ iter : expr , mut $ var : ident : $ t : tt $ ( $ r : tt ) * ) => { let mut $ var = read_value ! ( $ iter , $ t ) ; input_inner ! { $ iter $ ( $ r ) * } } ; ( $ iter : expr , mut $ var : ident $ ( $ r : tt ) * ) => { input_inner ! { $ iter , mut $ var : usize $ ( $ r ) * } } ; ( $ iter : expr , $ var : ident : $ t : tt $ ( $ r : tt ) * ) => { let $ var = read_value ! ( $ iter , $ t ) ; input_inner ! { $ iter $ ( $ r ) * } } ; ( $ iter : expr , $ var : ident $ ( $ r : tt ) * ) => { input_inner ! { $ iter , $ var : usize $ ( $ r ) * } } ; }
macro_rules ! read_value { ( $ iter : expr , ( $ ( $ t : tt ) ,* ) ) => { ( $ ( read_value ! ( $ iter , $ t ) ) ,* ) } ; ( $ iter : expr , [ $ t : tt ; $ len : expr ] ) => { ( 0 ..$ len ) . map ( | _ | read_value ! ( $ iter , $ t ) ) . collect ::< Vec < _ >> ( ) } ; ( $ iter : expr , { chars : $ base : expr } ) => { read_value ! ( $ iter , String ) . chars ( ) . map ( | c | ( c as u8 - $ base as u8 ) as usize ) . collect ::< Vec < usize >> ( ) } ; ( $ iter : expr , { char : $ base : expr } ) => { read_value ! ( $ iter , { chars : $ base } ) [ 0 ] } ; ( $ iter : expr , chars ) => { read_value ! ( $ iter , String ) . chars ( ) . collect ::< Vec < char >> ( ) } ; ( $ iter : expr , char ) => { read_value ! ( $ iter , chars ) [ 0 ] } ; ( $ iter : expr , usize1 ) => { read_value ! ( $ iter , usize ) - 1 } ; ( $ iter : expr , $ t : ty ) => { $ iter . next ( ) . unwrap ( ) . parse ::<$ t > ( ) . unwrap ( ) } ; }
pub trait Monoid {
    type T: Clone + PartialEq;
    fn mempty(&self) -> Self::T;
    fn mappend(&self, x: &Self::T, y: &Self::T) -> Self::T;
}
pub struct SegmentTree<M: Monoid> {
    n: usize,
    seg: Vec<M::T>,
    m: M,
}
impl<M: Monoid> SegmentTree<M> {
    pub fn new(n: usize, m: M) -> SegmentTree<M> {
        let n = 1 << format!("{:b}", n - 1).len();
        let seg = vec![m.mempty(); 2 * n - 1];
        SegmentTree {
            n: n,
            seg: seg,
            m: m,
        }
    }
    pub fn from_vec(v: Vec<M::T>, m: M) -> SegmentTree<M> {
        let n = 1 << format!("{:b}", v.len() - 1).len();
        let mut seg = vec![m.mempty(); 2 * n - 1];
        for (i, x) in v.into_iter().enumerate() {
            seg[i + n - 1] = x;
        }
        for i in (0..n - 1).rev() {
            seg[i] = m.mappend(&seg[2 * i + 1], &seg[2 * i + 2]);
        }
        SegmentTree {
            n: n,
            seg: seg,
            m: m,
        }
    }
    pub fn update(&mut self, k: usize, x: M::T) {
        let mut k = k + self.n - 1;
        self.seg[k] = x;
        while k > 0 {
            k = (k - 1) / 2;
            self.seg[k] = self.m.mappend(&self.seg[2 * k + 1], &self.seg[2 * k + 2]);
        }
    }
    pub fn query(&self, l: usize, r: usize) -> M::T {
        let mut l = l + self.n - 1;
        let mut r = r + self.n - 1;
        let mut res = self.m.mempty();
        while l < r {
            if r & 1 == 0 {
                r -= 1;
                res = self.m.mappend(&res, &self.seg[r]);
            }
            if l & 1 == 0 {
                res = self.m.mappend(&res, &self.seg[l]);
                l += 1;
            }
            l = (l - 1) / 2;
            r = (r - 1) / 2;
        }
        res
    }
}
pub struct MinMonoid<T: Ord + Clone> {
    min: T,
}
impl<T: Ord + Clone> MinMonoid<T> {
    pub fn new(min: T) -> MinMonoid<T> {
        MinMonoid { min: min }
    }
}
impl<T: Ord + Clone> Monoid for MinMonoid<T> {
    type T = T;
    fn mempty(&self) -> T {
        self.min.clone()
    }
    fn mappend(&self, x: &T, y: &T) -> T {
        std::cmp::min(x, y).clone()
    }
}
use std::collections::HashMap;
#[derive(Debug)]
pub struct TreeRec {
    n: usize,
    graph: Vec<Vec<(usize, usize, usize)>>,
    left: Vec<usize>,
    right: Vec<usize>,
    euler: Vec<(usize, usize)>,
    par: Vec<(usize, usize)>,
    query: Vec<(usize, usize, usize, usize)>,
    vc: Vec<HashMap<usize, (usize, usize)>>,
    acc: Vec<usize>,
}
impl TreeRec {
    pub fn new(n: usize, query: Vec<(usize, usize, usize, usize)>) -> TreeRec {
        let mut vc = (0..n).map(|_| HashMap::new()).collect::<Vec<_>>();
        for &(x, _y, u, v) in &query {
            vc[u].insert(x, (0, 0));
            vc[v].insert(x, (0, 0));
        }
        TreeRec {
            n: n,
            graph: vec![vec![]; n],
            left: vec![0; n],
            right: vec![0; n],
            euler: vec![],
            par: vec![(0, 0); n],
            query: query,
            vc: vc,
            acc: vec![0; n],
        }
    }
    pub fn add_edge(&mut self, u: usize, v: usize, c: usize, d: usize) {
        self.graph[u].push((v, c, d));
        self.graph[v].push((u, c, d));
    }
    pub fn dfs(&mut self, u: usize, p: usize, depth: usize) {
        self.left[u] = self.euler.len();
        self.euler.push((depth, u));
        for i in 0..self.graph[u].len() {
            let (v, _c, _d) = self.graph[u][i];
            if v != p {
                self.dfs(v, u, depth + 1);
                self.euler.push((depth, u));
            }
        }
        self.right[u] = self.euler.len() - 1;
    }
    pub fn dfs2(&mut self, u: usize, p: usize, depth: usize) {
        self.acc[u] = depth;
        let keys = self.vc[u].keys().cloned().collect::<Vec<_>>();
        for &c in &keys {
            self.vc[u].insert(c, self.par[c]);
        }
        for i in 0..self.graph[u].len() {
            let (v, c, d) = self.graph[u][i];
            if v != p {
                let (l, m) = self.par[c];
                self.par[c] = (l + d, m + 1);
                self.dfs2(v, u, depth + d);
                self.par[c] = (l, m);
            }
        }
    }
    pub fn solve(&mut self) {
        let n = self.n;
        self.dfs(0, n, 0);
        let seg = SegmentTree::from_vec(self.euler.clone(), MinMonoid::new((std::usize::MAX, n)));
        for &(x, _y, u, v) in &self.query {
            let p = min(
                seg.query(self.left[u], self.right[v] + 1),
                seg.query(self.left[v], self.right[u] + 1),
            )
            .1;
            self.vc[p].insert(x, (0, 0));
        }
        self.dfs2(0, n, 0);
        for &(x, y, u, v) in &self.query {
            let p = min(
                seg.query(self.left[u], self.right[v] + 1),
                seg.query(self.left[v], self.right[u] + 1),
            )
            .1;
            let &(lp, mp) = self.vc[p].get(&x).unwrap();
            let &(lu, mu) = self.vc[u].get(&x).unwrap();
            let &(lv, mv) = self.vc[v].get(&x).unwrap();
            let dp = self.acc[p] + y * mp - lp;
            let du = self.acc[u] + y * mu - lu;
            let dv = self.acc[v] + y * mv - lv;
            let ans = du + dv - 2 * dp;
            println!("{}", ans);
        }
    }
}
use std::cmp::min;
fn main() {
    input! { n, q, abcd: [(usize1,usize1,usize1,usize); n-1], xyuv: [(usize1,usize,usize1,usize1); q] };
    let mut rec = TreeRec::new(n, xyuv);
    for &(a, b, c, d) in &abcd {
        rec.add_edge(a, b, c, d);
    }
    rec.solve();
}


Measured memory_bytes: 161528