fn main() { input! { n: usize, a: [(usize1, usize1); n - 1], b: [(usize1, usize1); n - 1], } let mut g = vec![vec![]; n]; for (a, b) in a { g[a].push(b); g[b].push(a); } hld(&mut g); let state = State { vertex: vec![0; n] }; let mut stt = STT::new(state, 0, b); let mut ans = 0; let mut dfs = vec![(0, true, false)]; let mut memo = vec![]; while let Some((v, save, eval)) = dfs.pop() { if eval { for &u in g[v].iter().skip(1) { memo.push(u); } while let Some(u) = memo.pop() { stt.state.vertex[u] ^= 1; stt.update_vertex(u); memo.extend(g[u].iter().cloned()); } stt.state.vertex[v] ^= 1; stt.update_vertex(v); ans += stt.find().ans; if !save { memo.push(v); while let Some(u) = memo.pop() { stt.state.vertex[u] ^= 1; stt.update_vertex(u); memo.extend(g[u].iter().cloned()); } } } else { dfs.push((v, save, true)); for (i, &u) in g[v].iter().enumerate() { dfs.push((u, i == 0, false)); } } } println!("{}", 2 * ans); } fn sack(v: usize, save: bool, g: &[Vec], stt: &mut STT, ans: &mut u64) { for (i, &u) in g[v].iter().enumerate().rev() { sack(u, i == 0, g, stt, ans); } for &u in g[v].iter().skip(1) { flip(u, g, stt); } stt.state.vertex[v] ^= 1; stt.update_vertex(v); *ans += stt.find().ans; if !save { flip(v, g, stt); } } fn flip(v: usize, g: &[Vec], stt: &mut STT) { stt.state.vertex[v] ^= 1; stt.update_vertex(v); for &u in g[v].iter() { flip(u, g, stt); } } fn hld(g: &mut Vec>) { let mut size = vec![1; g.len()]; let mut topo = vec![0]; for i in 0..g.len() { let v = topo[i]; for u in g[v].clone() { g[u].retain(|p| *p != v); topo.push(u); } } for &v in topo.iter().rev() { g[v].sort_by_key(|u| !size[*u]); for &u in g[v].iter() { size[v] += size[u]; } } } struct State { vertex: Vec, } #[derive(Clone, Default, Debug)] struct Data { cnt: [u32; 2], ls: [u64; 2], rs: [u64; 2], ans: u64, len: u32, } impl TreeDP for State { type Path = Data; fn rake(&self, x: &Self::Path, y: &Self::Path) -> Self::Path { let mut res = Data::default(); res.ans = x.ans + y.ans; res.len = x.len; for i in 0..2 { res.cnt[i] = x.cnt[i] + y.cnt[i]; res.ls[i] = x.ls[i] + y.ls[i]; res.rs[i] = x.rs[i] + y.ls[i] + y.cnt[i] as u64 * x.len as u64; res.ans += x.cnt[i] as u64 * y.ls[i ^ 1]; res.ans += x.ls[i] * y.cnt[i ^ 1] as u64; } res } fn compress(&self, p: &Self::Path, c: &Self::Path) -> Self::Path { let mut res = Data::default(); res.ans = p.ans + c.ans; res.len = p.len + c.len; for i in 0..2 { res.cnt[i] = p.cnt[i] + c.cnt[i]; res.ls[i] = p.ls[i] + c.ls[i] + p.len as u64 * c.cnt[i] as u64; res.rs[i] = c.rs[i] + p.rs[i] + c.len as u64 * p.cnt[i] as u64; res.ans += p.cnt[i] as u64 * c.ls[i ^ 1]; res.ans += p.rs[i] * c.cnt[i ^ 1] as u64; } res } fn build(&self, v: usize, _e: usize) -> Self::Path { let x = self.vertex[v] as usize; let mut res = Data::default(); res.cnt[x] += 1; res.ls[x] += 1; res.len = 1; res } } // ---------- begin input macro ---------- // reference: https://qiita.com/tanakh/items/0ba42c7ca36cd29d0ac8 #[macro_export] macro_rules! input { (source = $s:expr, $($r:tt)*) => { 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_export] macro_rules! input_inner { ($iter:expr) => {}; ($iter:expr, ) => {}; ($iter:expr, $var:ident : $t:tt $($r:tt)*) => { let $var = read_value!($iter, $t); input_inner!{$iter $($r)*} }; } #[macro_export] 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::>() }; ($iter:expr, chars) => { read_value!($iter, String).chars().collect::>() }; ($iter:expr, bytes) => { read_value!($iter, String).bytes().collect::>() }; ($iter:expr, usize1) => { read_value!($iter, usize) - 1 }; ($iter:expr, $t:ty) => { $iter.next().unwrap().parse::<$t>().expect("Parse error") }; } // ---------- end input macro ---------- pub trait TreeDP { type Path: Clone; fn rake(&self, x: &Self::Path, y: &Self::Path) -> Self::Path; fn compress(&self, p: &Self::Path, c: &Self::Path) -> Self::Path; fn build(&self, v: usize, e: usize) -> Self::Path; } pub struct STT { node: UVec>, label: UVec