macro_rules! input {
    (source = $s:expr, $($r:tt)*) => {
        let mut iter = $s.split_whitespace();
        let mut next = || { iter.next().unwrap() };
        input_inner!{next, $($r)*}
    };
    ($($r:tt)*) => {
        let stdin = std::io::stdin();
        let mut bytes = std::io::Read::bytes(std::io::BufReader::new(stdin.lock()));
        let mut next = move || -> String {
            bytes
                .by_ref()
                .map(|r| r.unwrap() as char)
                .skip_while(|c| c.is_whitespace())
                .take_while(|c| !c.is_whitespace())
                .collect()
        };
        input_inner!{next, $($r)*}
    };
}

macro_rules! input_inner {
    ($next:expr) => {};
    ($next:expr, ) => {};

    ($next:expr, $var:ident : $t:tt $($r:tt)*) => {
        let $var = read_value!($next, $t);
        input_inner!{$next $($r)*}
    };

    ($next:expr, mut $var:ident : $t:tt $($r:tt)*) => {
        let mut $var = read_value!($next, $t);
        input_inner!{$next $($r)*}
    };
}

macro_rules! read_value {
    ($next:expr, ( $($t:tt),* )) => {
        ( $(read_value!($next, $t)),* )
    };

    ($next:expr, [ $t:tt ; $len:expr ]) => {
        (0..$len).map(|_| read_value!($next, $t)).collect::<Vec<_>>()
    };

    ($next:expr, [ $t:tt ]) => {
        {
            let len = read_value!($next, usize);
            (0..len).map(|_| read_value!($next, $t)).collect::<Vec<_>>()
        }
    };

    ($next:expr, chars) => {
        read_value!($next, String).chars().collect::<Vec<char>>()
    };

    ($next:expr, usize1) => {
        read_value!($next, usize) - 1
    };

    ($next:expr, $t:ty) => {
        $next().parse::<$t>().expect("Parse error")
    };
}

#[allow(unused_imports)]
use std::cmp::{min, max};

fn main() {
    input!{
        n: usize,
        q: usize,
        es: [(usize1, usize1, usize, usize); n - 1],
        qs: [(usize, usize, usize1, usize1); q]
    }
    let mut t = vec![vec![]; n];
    for &(a, b, c, d) in &es {
        t[a].push((b, c, d));
        t[b].push((a, c, d));
    }
    let lca = Lca::new(0, &t.iter().map(|x| x.iter().map(|y| y.0).collect()).collect());
    let mut ds = vec![0; n];
    let mut cs = vec![0; n];
    let mut dist = vec![0; n];
    let mut cdist = vec![vec![(0, 0, 0)]; n];
    let mut ord = vec![0; n];
    dfs(0, 0, &t, &mut 0, &mut ds, &mut cs, &mut dist, &mut cdist, &mut ord);
    for &(x, y, u, v) in &qs {
        let p = lca.query(u, v);
        let duv = dist[u] + dist[v] - 2 * dist[p];
        let ui = binary_search_last(0, cdist[x].len() - 1, |m| cdist[x][m].0 <= ord[u]);
        let vi = binary_search_last(0, cdist[x].len() - 1, |m| cdist[x][m].0 <= ord[v]);
        let pi = binary_search_last(0, cdist[x].len() - 1, |m| cdist[x][m].0 <= ord[p]);
        let xuv = cdist[x][ui].1 + cdist[x][vi].1 - 2 * cdist[x][pi].1;
        let cuv = cdist[x][ui].2 + cdist[x][vi].2 - 2 * cdist[x][pi].2;
        println!("{}", duv - xuv + y * cuv);
    }
}

fn dfs(r: usize, p: usize, t: &Vec<Vec<(usize, usize, usize)>>, l: &mut usize, ds: &mut Vec<usize>, cs: &mut Vec<usize>, dist: &mut Vec<usize>, cdist: &mut Vec<Vec<(usize, usize, usize)>>, ord: &mut Vec<usize>) {
    for &(v, c, d) in &t[r] {
        if v == p {
            continue;
        }
        *l += 1;
        ord[v] = *l;
        ds[c] += d;
        cs[c] += 1;
        dist[v] = dist[r] + d;
        cdist[c].push((*l, ds[c], cs[c]));
        dfs(v, r, t, l, ds, cs, dist, cdist, ord);
        *l += 1;
        ds[c] -= d;
        cs[c] -= 1;
        cdist[c].push((*l, ds[c], cs[c]));
    }
}

fn binary_search_last<F>(mut l: usize, mut r: usize, mut f: F) -> usize where F: FnMut(usize) -> bool {
    if f(r) {
        return r;
    }
    while l + 1 < r {
        let m = (l + r) / 2;
        if f(m) {
            l = m;
        } else {
            r = m;
        }
    }
    l
}

struct Lca {
    anc: Vec<Vec<usize>>,
    dep: Vec<usize>
}

impl Lca {
    fn new(r: usize, t: &Vec<Vec<usize>>) -> Lca {
        let n = t.len();
        let k = 64 - n.leading_zeros() as usize;
        let mut anc = vec![vec![0; n]; k];
        let mut par = vec![n; n];
        let mut dep = vec![n; n];
        par[r] = r;
        dep[r] = 0;
        Lca::lca_dfs(r, t, &mut par, &mut dep);
        anc[0] = par;
        for i in 0..k - 1 {
            for j in 0..n {
                anc[i + 1][j] = anc[i][anc[i][j]];
            }
        }
        Lca {anc: anc, dep: dep}
    }

    fn lca_dfs(r: usize, t: &Vec<Vec<usize>>, par: &mut Vec<usize>, dep: &mut Vec<usize>) {
        for &c in &t[r] {
            if par[c] == t.len() {
                par[c] = r;
                dep[c] = dep[r] + 1;
                Lca::lca_dfs(c, t, par, dep);
            }
        }
    }

    fn query(&self, mut a: usize, mut b: usize) -> usize {
        if self.dep[a] > self.dep[b] {
            let mut p = self.dep[a] - self.dep[b];
            while p > 0 {
                let lm1 = p.trailing_zeros() as usize;
                a = self.anc[lm1][a];
                p ^= 1 << lm1;
            }
        } else if self.dep[a] < self.dep[b] {
            let mut p = self.dep[b] - self.dep[a];
            while p > 0 {
                let lm1 = p.trailing_zeros() as usize;
                b = self.anc[lm1][b];
                p ^= 1 << lm1;
            }
        }
        if a == b {
            return a;
        }
        loop {
            if self.anc[0][a] == self.anc[0][b] {
                return self.anc[0][a];
            }
            let mut l = 0;
            let mut r = self.anc.len();
            while l + 1 < r {
                let m = (l + r) / 2;
                if self.anc[m][a] == self.anc[m][b] {
                    r = m;
                } else {
                    l = m;
                }
            }
            a = self.anc[l][a];
            b = self.anc[l][b];
        }
    }
}


Measured memory_bytes: 77436