#![allow(unused_imports)]
#![allow(non_snake_case)]
use std::cmp::*;
use std::collections::*;
use std::io::Write;

#[allow(unused_macros)]
macro_rules! debug {
    ($($e:expr),*) => {
        #[cfg(debug_assertions)]
        $({
            let (e, mut err) = (stringify!($e), std::io::stderr());
            writeln!(err, "{} = {:?}", e, $e).unwrap()
        })*
    };
}

#[derive(Clone)]
struct Query {
    q_idx: usize,
    color: usize,
    cost: i64,
    coef: i64,
}

fn main() {
    let v = read_vec::<usize>();
    let (n, q) = (v[0], v[1]);

    let mut g = vec![Vec::new(); n];
    let mut color_dict = HashMap::new();
    let mut dist_dict = HashMap::new();
    for i in 0..n - 1 {
        let v = read_vec::<usize>();
        let (a, b, c, d) = (v[0] - 1, v[1] - 1, v[2], v[3] as i64);
        g[b].push(a);
        g[a].push(b);
        color_dict.insert((a, b), c);
        color_dict.insert((b, a), c);
        dist_dict.insert((a, b), d);
        dist_dict.insert((b, a), d);
    }
    let lca = LCA::new(&g);
    let mut tree: Vec<Vec<usize>> = vec![Vec::new(); n];
    let mut parent_dict: HashMap<usize, usize> = HashMap::new();
    make_tree(0, n, &g, &mut tree, &mut parent_dict);
    let mut topological_sorted_indexes = vec![0];
    topological_dfs(0, &tree, &mut topological_sorted_indexes);

    let mut dist_from_root = vec![0i64; n];

    for &ti in topological_sorted_indexes.iter().skip(1) {
        let parent = parent_dict[&ti];
        dist_from_root[ti] = dist_from_root[parent] + dist_dict[&(ti, parent)];
    }
    let mut answers = vec![0i64; q];
    let mut queries = vec![vec![]; n];
    for q_idx in 0..q {
        let v = read_vec::<usize>();
        let (color, cost, u, v) = (v[0], v[1] as i64, v[2] - 1, v[3] - 1);
        let common = lca.lca(u, v);
        queries[u].push(Query {
            q_idx: q_idx,
            color: color,
            cost: cost,
            coef: 1,
        });
        queries[v].push(Query {
            q_idx: q_idx,
            color: color,
            cost: cost,
            coef: 1,
        });
        queries[common].push(Query {
            q_idx: q_idx,
            color: color,
            cost: cost,
            coef: -2,
        });
        answers[q_idx] = dist_from_root[u] + dist_from_root[v] - 2 * dist_from_root[common];
    }
    let mut count = vec![0; n];
    let mut sum = vec![0; n];
    dfs(
        0,
        &tree,
        &color_dict,
        &dist_dict,
        &queries,
        &mut count,
        &mut sum,
        &mut answers,
    );
    for ans in answers {
        println!("{}", ans);
    }
}

fn dfs(
    cur: usize,
    tree: &Vec<Vec<usize>>,
    color_dict: &HashMap<(usize, usize), usize>,
    dist_dict: &HashMap<(usize, usize), i64>,
    queries: &Vec<Vec<Query>>,
    count: &mut Vec<i64>,
    sum: &mut Vec<i64>,
    answers: &mut Vec<i64>,
) {
    for ref q in queries[cur].iter() {
        answers[q.q_idx] += (q.cost * count[q.color] - sum[q.color]) * q.coef;
    }
    let childlen = tree[cur].iter().cloned().collect::<Vec<_>>();
    for child in childlen {
        let color = color_dict[&(cur, child)];
        count[color] += 1;
        sum[color] += dist_dict[&(cur, child)];
        dfs(
            child, tree, color_dict, dist_dict, queries, count, sum, answers,
        );
        count[color] -= 1;
        sum[color] -= dist_dict[&(cur, child)];
    }
}

fn read<T: std::str::FromStr>() -> T {
    let mut s = String::new();
    std::io::stdin().read_line(&mut s).ok();
    s.trim().parse().ok().unwrap()
}

fn read_vec<T: std::str::FromStr>() -> Vec<T> {
    read::<String>()
        .split_whitespace()
        .map(|e| e.parse().ok().unwrap())
        .collect()
}

pub struct LCA {
    pub depth: Vec<usize>,
    pub parent: Vec<Vec<Option<usize>>>,
}

pub struct Tree {
    pub root: usize,
    pub parent: Vec<Option<usize>>,
    pub childs: Vec<Vec<usize>>,
}

impl LCA {
    pub fn new(g: &[Vec<usize>]) -> LCA {
        LCA::with_root(0, g)
    }

    pub fn with_root(root: usize, g: &[Vec<usize>]) -> LCA {
        fn dfs(
            i: usize,
            p: Option<usize>,
            d: usize,
            g: &[Vec<usize>],
            depth: &mut [usize],
            parent: &mut [Vec<Option<usize>>],
        ) {
            parent[i][0] = p;
            depth[i] = d;

            for &t in &g[i] {
                if Some(t) != p {
                    dfs(t, Some(i), d + 1, g, depth, parent);
                }
            }
        }
        let n = g.len();
        let l2 = (1..).find(|i| 1usize << i > n).unwrap();
        let mut depth = vec![0; n];
        let mut parent = vec![vec![None; l2 + 1]; n];

        dfs(root, None, 0, &g, &mut depth, &mut parent);

        for i in 1..l2 + 1 {
            for j in 0..n {
                if let Some(p) = parent[j][i - 1] {
                    parent[j][i] = parent[p][i - 1];
                }
            }
        }

        LCA {
            depth: depth,
            parent: parent,
        }
    }

    pub fn lca(&self, mut a: usize, mut b: usize) -> usize {
        use std::mem::swap;
        if self.depth[b] < self.depth[a] {
            swap(&mut a, &mut b);
        }

        while self.depth[a] != self.depth[b] {
            b = self.parent[b][(self.depth[b] - self.depth[a]).trailing_zeros() as usize].unwrap();
        }

        if a == b {
            return a;
        }

        for i in (0..self.parent[0].len()).rev() {
            if self.parent[a][i] != self.parent[b][i] {
                a = self.parent[a][i].unwrap();
                b = self.parent[b][i].unwrap();
            }
        }
        self.parent[a][0].unwrap()
    }
}

fn make_tree(
    cur_idx: usize,
    parent_idx: usize,
    edges: &Vec<Vec<usize>>,
    tree: &mut Vec<Vec<usize>>,
    parent_dict: &mut HashMap<usize, usize>,
) {
    for child_idx in edges[cur_idx].iter() {
        if *child_idx == parent_idx {
            continue;
        }
        tree[cur_idx].push(*child_idx);
        parent_dict.insert(*child_idx, cur_idx);
        make_tree(*child_idx, cur_idx, edges, tree, parent_dict);
    }
}

fn topological_dfs(cur_idx: usize, tree: &Vec<Vec<usize>>, result: &mut Vec<usize>) {
    for child_idx in tree[cur_idx].iter() {
        result.push(*child_idx);
        topological_dfs(*child_idx, tree, result);
    }
}


Measured memory_bytes: 129628