nekolib/graph/tree_cata.rs
1//! 全方位木 DP。
2
3use std::collections::VecDeque;
4
5/// 全方位木 DP。
6///
7/// 木の catamorphism。
8/// 各頂点を根としたときのものをまとめて求める。
9///
10/// 二項演算 $\circ: S\\times S\\to S$ と $\star: S\\times T\\to S$ を考える。
11/// $(S, \\circ)$ は単位元 $\\mathrm{id}\_{\\circ}$ を持つモノイドとする。
12/// 木の各辺は一つずつ $T$ の値を持っているとし、辺 $(v, u)$ の値を $e\_{v, u}$
13/// とする。
14///
15/// 頂点 $v$ が葉のとき、$f(v) = \\mathrm{id}\_{\\circ}$ とする[^1]。
16/// そうでないとき、$v$ に隣接する頂点を順に
17/// $\\langle u\_1, u\_2, \\dots, u\_k\\rangle$ とする。$v$ が根のとき、
18/// $$ f(v) = (f\_v(u\_1)\\star e\_{u\_1, v})\\circ\\dots\\circ(f\_v(u\_k)\\star e\_{u\_k, v}) $$
19/// で定める。ただし、$f\_v(u)$ は、「$v$ を取り除いた森において $u$ を含む木で
20/// $u$ を根としたもの」における $f(u)$ とする。
21///
22/// [^1]: すなわち、頂点数 1 の木における $f$ の値が $\\mathrm{id}\_{\\circ}$ となる。
23///
24/// <img src="../../../../images/tree_cata.png" width="300" alt=""><img src="../../../../../images/tree_cata.png" width="300" alt="">
25///
26/// 上図グラフにおいて、頂点 $1$ に隣接する頂点のうち、$0$ が最後に来るものとすれば
27/// $$ \\begin{aligned}
28/// f(1) &= f\_0(1)\\circ(f\_1(0)\\star e\_{0, 1}) \\\\
29/// &= f\_0(1) \\circ ((f\_0(2)\\star e\_{2, 0})\\star e\_{0, 1})
30/// \\end{aligned} $$
31/// のようになる。
32///
33/// このように定められる $f$ に対し、$f(0), f(1), \\dots, f(n-1)$ を求める。
34///
35/// # Idea
36/// まず、根を $0$ として木をトポロジカルソートしておく。
37/// これにより、ボトムアップの DP を単にループで行うことができ、$f(0)$
38/// が求まる。次に、上で $f(1)$ を求めたときのように、トップダウンに DP
39/// をしながら(ボトムアップの DP での結果を利用して)残りの頂点について求める。
40///
41/// ## Implementation notes
42/// トポロジカルソートの前処理パートは、木が同じであれば $(\\circ, \\star)$
43/// に依らないので使い回しできる。
44///
45/// 実装においては、$\\circ: S\\times S\\to S$ を `fold`、$\\mathrm{id}\_{\\circ}$
46/// を `empty`、$\\star: S\\times T\\to S$ を `map` と呼んでいる。
47///
48/// `empty` は葉での値(頂点数 1 の木での値)と `fold` の単位元に対応している。
49/// 葉の値を特別扱いしたいときは、セグ木に半群を乗せるときのように、
50/// フラグを持たせれば対応できる(下記の root-leaf の距離の総和の例を参照)。
51/// 全体の頂点数が 1 だったときの処理を最後に分ける必要があるので注意。
52///
53/// 各頂点における頂点の順序を気にした実装になっているため、「各頂点を根として
54/// DFS したときの post-order で各頂点を並べ、その列に基数 $b$・法 $m$ の
55/// rolling hash を適用したときの値を求めよ」といった問題も処理できるはず。
56/// ハッシュ値 $h$ と、部分木サイズ $k$ に対して $(h, b^k\\bmod m)$
57/// とかを管理すればよさそう。
58///
59/// # Complexity
60/// $O(n)$ time.
61///
62/// # Examples
63/// ```
64/// use nekolib::graph::TreeCata;
65///
66/// let g = vec![
67/// vec![(1, ()), (2, ())],
68/// vec![(0, ()), (3, ()), (4, ()), (5, ())],
69/// vec![(0, ())],
70/// vec![(1, ())],
71/// vec![(1, ())],
72/// vec![(1, ())],
73/// ];
74///
75/// // 0 -- 2
76/// // |
77/// // 4 -- 1 -- 3
78/// // |
79/// // 5
80///
81/// let tc: TreeCata<_> = g.into();
82///
83/// // max distance
84/// let empty = 0;
85/// let map = |&x: &usize, _: &()| x + 1;
86/// let fold = |&x: &usize, &y: &usize| x.max(y);
87/// assert_eq!(tc.each_root(empty, map, fold), [2, 2, 3, 3, 3, 3]);
88///
89/// // sum of distance
90/// let empty = (0, 0);
91/// let map = |&(d, c): &(usize, usize), _: &()| (d + c + 1, c + 1);
92/// let fold =
93/// |&x: &(usize, usize), &y: &(usize, usize)| (x.0 + y.0, x.1 + y.1);
94/// assert_eq!(
95/// tc.each_root(empty, map, fold)
96/// .into_iter()
97/// .map(|x| x.0)
98/// .collect::<Vec<_>>(),
99/// [8, 6, 12, 10, 10, 10]
100/// );
101///
102/// // (sum of root-leaf distance, # of leaves)
103/// let empty = ((0, 0), false);
104/// let map = |&(x, inner): &((usize, usize), bool), _: &()| {
105/// let (x1, x0) = if inner { x } else { (0, 1) };
106/// ((x1 + 1 * x0, x0), true)
107/// };
108/// let fold = |&x: &((usize, usize), bool), &y: &((usize, usize), bool)| {
109/// let (x1, x0) = x.0;
110/// let (y1, y0) = y.0;
111/// ((x1 + y1, x0 + y0), x.1 | y.1)
112/// };
113/// assert_eq!(
114/// tc.each_root(empty, map, fold)
115/// .into_iter()
116/// .map(|x| if x.1 { x.0 } else { (0, 1) })
117/// .collect::<Vec<_>>(),
118/// [(7, 4), (5, 4), (9, 3), (7, 3), (7, 3), (7, 3)]
119/// );
120/// ```
121///
122/// ```
123/// use nekolib::graph::TreeCata;
124///
125/// let g = vec![
126/// vec![(1, 0), (2, 0)],
127/// vec![(0, 1), (3, 1), (4, 1), (5, 1)],
128/// vec![(0, 2)],
129/// vec![(1, 3)],
130/// vec![(1, 4)],
131/// vec![(1, 5)],
132/// ];
133///
134/// let tc: TreeCata<_> = g.into();
135///
136/// let empty = "".to_owned();
137/// let map = |x: &String, c: &usize| {
138/// if x == "" { format!("{}: []", c) } else { format!("{}: [{}]", c, x) }
139/// };
140/// let fold = |x: &String, y: &String| {
141/// if x == "" && y == "" {
142/// "".to_owned()
143/// } else if x != "" && y != "" {
144/// format!("{}, {}", x, y)
145/// } else {
146/// format!("{}{}", x, y)
147/// }
148/// };
149///
150/// let actual = tc
151/// .each_root(empty, map, fold)
152/// .into_iter()
153/// .enumerate()
154/// .map(|(i, x)| format!("{}: [{}]", i, x))
155/// .collect::<Vec<_>>();
156///
157/// assert_eq!(
158/// actual,
159/// [
160/// "0: [1: [3: [], 4: [], 5: []], 2: []]",
161/// "1: [0: [2: []], 3: [], 4: [], 5: []]",
162/// "2: [0: [1: [3: [], 4: [], 5: []]]]",
163/// "3: [1: [0: [2: []], 4: [], 5: []]]",
164/// "4: [1: [0: [2: []], 3: [], 5: []]]",
165/// "5: [1: [0: [2: []], 3: [], 4: []]]",
166/// ]
167/// );
168///
169/// let empty = "".to_owned();
170/// let map = |x: &String, c: &usize| format!("({} {} )", x, c);
171/// let fold = |x: &String, y: &String| format!("{}{}", x, y);
172///
173/// assert_eq!(tc.each_root(empty, map, fold), [
174/// "(( 3 )( 4 )( 5 ) 1 )( 2 )",
175/// "(( 2 ) 0 )( 3 )( 4 )( 5 )",
176/// "((( 3 )( 4 )( 5 ) 1 ) 0 )",
177/// "((( 2 ) 0 )( 4 )( 5 ) 1 )",
178/// "((( 2 ) 0 )( 3 )( 5 ) 1 )",
179/// "((( 2 ) 0 )( 3 )( 4 ) 1 )",
180/// ]);
181/// ```
182///
183/// ## Applications
184/// AtCoder における利用例。$(S, \\circ, \\mathrm{id}\_{\\circ}, T, \\star)$
185/// の定義と、$\\langle f(0), f(1), \\dots, f(n-1)\\rangle$
186/// を用いて答えを得る部分のみ載せている。
187///
188/// ```ignore
189/// // typical90_am
190/// let empty = (0, 0);
191/// let map = |&x: &(usize, usize), _: &()| (x.0 + x.1 + 1, x.1 + 1);
192/// let fold =
193/// |&x: &(usize, usize), &y: &(usize, usize)| (x.0 + y.0, x.1 + y.1);
194/// let res: usize =
195/// tc.each_root(empty, map, fold).into_iter().map(|x| x.0).sum();
196/// ```
197/// ```ignore
198/// // abc220_f
199/// let empty = (0, 0);
200/// let map = |&(x1, x0): &(usize, usize), _: &()| (x1 + x0 + 1, x0 + 1);
201/// let fold = |&(x1, x0): &(usize, usize), &(y1, y0): &(usize, usize)| {
202/// (x1 + y1, x0 + y0)
203/// };
204/// let res: Vec<_> =
205/// tc.each_root(empty, map, fold).into_iter().map(|(x1, _)| x1).collect();
206/// ```
207/// ```ignore
208/// // abc222_f
209/// let empty = 0;
210/// let map = |&x: &i64, &(d, w): &(i64, i64)| x.max(d) + w;
211/// let fold = |&x: &i64, &y: &i64| x.max(y);
212/// let res = tc.each_root(empty, map, fold);
213/// ```
214/// ```ignore
215/// // abc223_g
216/// let empty = false;
217/// let map = |&x: &bool, _: &()| !x;
218/// let fold = |&x: &bool, &y: &bool| x | y;
219/// let res =
220/// tc.each_root(empty, map, fold).into_iter().filter(|&x| !x).count();
221/// ```
222/// ```ignore
223/// // s8pc_4_d
224/// let empty = (0.0, 0);
225/// let map = |&x: &(f64, usize), _: &()| (x.0 + 1.0, 1);
226/// let fold = |&x: &(f64, usize), &y: &(f64, usize)| {
227/// let v = x.0 * x.1 as f64 + y.0 * y.1 as f64;
228/// let d = x.1 + y.1;
229/// (v / 1.0_f64.max(d as f64), d)
230/// };
231/// let res = tc.each_root(empty, map, fold);
232/// ```
233/// ```ignore
234/// // dp_v
235/// let empty = 1;
236/// let map = |&x: &u64, _: &()| (x + 1) % m;
237/// let fold = |&x: &u64, &y: &u64| x * y % m;
238/// let res = tc.each_root(empty, map, fold);
239/// ```
240/// ```ignore
241/// // dp_p, abc036_d
242/// let empty = (1, 1);
243/// let map = |&x: &(u64, u64), _: &()| ((x.0 + x.1) % MOD, x.0);
244/// let fold =
245/// |&x: &(u64, u64), &y: &(u64, u64)| (x.0 * y.0 % MOD, x.1 * y.1 % MOD);
246/// let res: Vec<_> = tc
247/// .each_root(empty, map, fold)
248/// .into_iter()
249/// .map(|x| (x.0 + x.1) % MOD)
250/// .collect();
251/// assert!(res.iter().all(|&x| x == res[0]));
252/// ```
253/// ```ignore
254/// // abc160_f
255/// let mfb = ModFactorialBinom::new(n, MOD);
256/// let f = |i| mfb.factorial(i);
257/// let fr = |i| mfb.factorial_recip(i);
258///
259/// let empty = (0, 1, 1);
260/// let map = |&x: &(usize, u64, u64), _: &()| {
261/// (x.0 + 1, fr(x.0 + 1), x.1 * x.2 % MOD * f(x.0) % MOD)
262/// };
263/// let fold = |&x: &(usize, u64, u64), &y: &(usize, u64, u64)| {
264/// (x.0 + y.0, (x.1 * y.1) % MOD, (x.2 * y.2) % MOD)
265/// };
266/// let res: Vec<_> = tc
267/// .each_root(empty, map, fold)
268/// .into_iter()
269/// .map(|x| map(&x, &()).2)
270/// .collect();
271///
272/// // tdpc_tree
273/// let res =
274/// res.into_iter().fold(0_u64, |x, y| (x + y) % MOD) * mfb.recip(2) % MOD;
275/// ```
276///
277/// # References
278/// - <https://qiita.com/Kiri8128/items/a011c90d25911bdb3ed3>
279/// - トポロジカルソートで求める話が書かれている。
280/// - <https://fsharpforfunandprofit.com/posts/recursive-types-and-folds-1b/>
281/// - catamorphism の話が載っている。
282pub struct TreeCata<T> {
283 par: Vec<Option<(usize, T)>>,
284 order: Vec<usize>,
285 child: Vec<Vec<(usize, T)>>,
286 bound: Vec<usize>,
287}
288
289impl<T> From<Vec<Vec<(usize, T)>>> for TreeCata<T> {
290 fn from(mut g: Vec<Vec<(usize, T)>>) -> Self {
291 let n = g.len();
292 let mut par: Vec<_> = (0..n).map(|_| None).collect();
293 let mut q: VecDeque<_> = vec![0].into();
294 let mut order = vec![];
295 let mut child: Vec<_> = (0..n).map(|_| vec![]).collect();
296 let mut bound = vec![n; n];
297
298 while let Some(v) = q.pop_front() {
299 order.push(v);
300 let gv = std::mem::take(&mut g[v]);
301 let mut left = true;
302 for (nv, w) in gv {
303 if nv == 0 || par[nv].is_some() {
304 par[v] = Some((nv, w));
305 left = false;
306 } else {
307 if !left && bound[v] == n {
308 bound[v] = nv;
309 }
310 child[v].push((nv, w));
311 q.push_back(nv);
312 }
313 }
314 }
315
316 Self { par, order, child, bound }
317 }
318}
319
320impl<T> TreeCata<T> {
321 pub fn each_root<U: Clone>(
322 &self,
323 empty: U,
324 mut map: impl FnMut(&U, &T) -> U,
325 mut fold: impl FnMut(&U, &U) -> U,
326 ) -> Vec<U> {
327 let n = self.child.len();
328 if n == 0 {
329 return vec![];
330 }
331
332 let mut ascl: Vec<_> = vec![empty.clone(); n];
333 let mut ascr: Vec<_> = vec![empty.clone(); n];
334 let mut dp: Vec<_> = vec![empty.clone(); n];
335 let mut right: Vec<_> = self.bound.iter().map(|&bi| bi < n).collect();
336 for &i in self.order[1..].iter().rev() {
337 dp[i] = fold(&ascl[i], &ascr[i]);
338 let &(p, ref x) = self.par[i].as_ref().unwrap();
339 if right[p] {
340 ascr[p] = fold(&map(&dp[i], x), &ascr[p]);
341 right[p] = self.bound[p] != i;
342 } else {
343 ascl[p] = fold(&map(&dp[i], x), &ascl[p]);
344 }
345 }
346 dp[0] = fold(&ascl[0], &ascr[0]);
347
348 let mut desc: Vec<_> = vec![empty.clone(); n];
349 for &i in &self.order {
350 let mut ac = desc[i].clone();
351 for &(j, _) in &self.child[i] {
352 let x = &self.par[j].as_ref().unwrap().1;
353 desc[j] = ac.clone();
354 ac = fold(&ac, &map(&dp[j], x));
355 }
356 let mut ac = empty.clone();
357 for &(j, ref x) in self.child[i].iter().rev() {
358 desc[j] = map(&fold(&desc[j], &ac), x);
359 let x = &self.par[j].as_ref().unwrap().1;
360 ac = fold(&map(&dp[j], x), &ac);
361 let tmp = fold(&desc[j], &ascr[j]);
362 dp[j] = fold(&ascl[j], &tmp);
363 }
364 }
365 dp
366 }
367}
368
369#[test]
370fn test_value() {
371 let n = 6;
372 let es = vec![(0, 1), (0, 2), (1, 3), (1, 4), (1, 5)];
373 let g = {
374 let mut g = vec![vec![]; n];
375 for &(u, v) in &es {
376 g[u].push((v, ()));
377 g[v].push((u, ()));
378 }
379 g
380 };
381 let tree_cata: TreeCata<_> = g.into();
382
383 // max distance
384 let empty = 0;
385 let map = |&x: &usize, _: &()| x + 1;
386 let fold = |&x: &usize, &y: &usize| x.max(y);
387 assert_eq!(tree_cata.each_root(empty, map, fold), [2, 2, 3, 3, 3, 3]);
388
389 // sum of distance
390 let empty = (0, 0);
391 let map = |&(d, c): &(usize, usize), _: &()| (d + c + 1, c + 1);
392 let fold =
393 |&x: &(usize, usize), &y: &(usize, usize)| (x.0 + y.0, x.1 + y.1);
394 assert_eq!(
395 tree_cata
396 .each_root(empty, map, fold)
397 .into_iter()
398 .map(|x| x.0)
399 .collect::<Vec<_>>(),
400 [8, 6, 12, 10, 10, 10]
401 );
402
403 let g = vec![
404 vec![(1, 0), (2, 0)],
405 vec![(0, 1), (3, 1), (4, 1), (5, 1)],
406 vec![(0, 2)],
407 vec![(1, 3)],
408 vec![(1, 4)],
409 vec![(1, 5)],
410 ];
411 let tree_cata: TreeCata<_> = g.into();
412
413 // string representation
414 let empty = "".to_owned();
415 let map = |x: &String, c: &usize| {
416 if x == "" { format!("{}: []", c) } else { format!("{}: [{}]", c, x) }
417 };
418 let fold = |x: &String, y: &String| {
419 if x == "" && y == "" {
420 "".to_owned()
421 } else if x != "" && y != "" {
422 format!("{}, {}", x, y)
423 } else {
424 format!("{}{}", x, y)
425 }
426 };
427
428 let actual = tree_cata
429 .each_root(empty, map, fold)
430 .into_iter()
431 .enumerate()
432 .map(|(i, x)| format!("{}: [{}]", i, x))
433 .collect::<Vec<_>>();
434
435 let expected = [
436 "0: [1: [3: [], 4: [], 5: []], 2: []]",
437 "1: [0: [2: []], 3: [], 4: [], 5: []]",
438 "2: [0: [1: [3: [], 4: [], 5: []]]]",
439 "3: [1: [0: [2: []], 4: [], 5: []]]",
440 "4: [1: [0: [2: []], 3: [], 5: []]]",
441 "5: [1: [0: [2: []], 3: [], 4: []]]",
442 ];
443 assert_eq!(actual, expected);
444}
445
446#[test]
447fn test_order() {
448 let empty = || "".to_owned();
449 let map = |x: &String, c: &usize| format!("({} {} )", x, c);
450 let fold = |x: &String, y: &String| format!("{}{}", x, y);
451
452 // leftmost
453 let g = vec![
454 vec![(1, 0), (2, 0)],
455 vec![(0, 1), (3, 1), (4, 1), (5, 1)],
456 vec![(0, 2)],
457 vec![(1, 3)],
458 vec![(1, 4)],
459 vec![(1, 5)],
460 ];
461
462 let tree_cata: TreeCata<_> = g.into();
463 assert_eq!(tree_cata.each_root(empty(), map, fold), [
464 "(( 3 )( 4 )( 5 ) 1 )( 2 )",
465 "(( 2 ) 0 )( 3 )( 4 )( 5 )",
466 "((( 3 )( 4 )( 5 ) 1 ) 0 )",
467 "((( 2 ) 0 )( 4 )( 5 ) 1 )",
468 "((( 2 ) 0 )( 3 )( 5 ) 1 )",
469 "((( 2 ) 0 )( 3 )( 4 ) 1 )",
470 ]);
471
472 // inner (1)
473 let g = vec![
474 vec![(1, 0), (2, 0)],
475 vec![(3, 1), (0, 1), (4, 1), (5, 1)],
476 vec![(0, 2)],
477 vec![(1, 3)],
478 vec![(1, 4)],
479 vec![(1, 5)],
480 ];
481
482 let tree_cata: TreeCata<_> = g.into();
483 assert_eq!(tree_cata.each_root(empty(), map, fold), [
484 "(( 3 )( 4 )( 5 ) 1 )( 2 )",
485 "( 3 )(( 2 ) 0 )( 4 )( 5 )",
486 "((( 3 )( 4 )( 5 ) 1 ) 0 )",
487 "((( 2 ) 0 )( 4 )( 5 ) 1 )",
488 "((( 2 ) 0 )( 3 )( 5 ) 1 )",
489 "((( 2 ) 0 )( 3 )( 4 ) 1 )",
490 ]);
491
492 // inner (2)
493 let g = vec![
494 vec![(1, 0), (2, 0)],
495 vec![(3, 1), (4, 1), (0, 1), (5, 1)],
496 vec![(0, 2)],
497 vec![(1, 3)],
498 vec![(1, 4)],
499 vec![(1, 5)],
500 ];
501
502 let tree_cata: TreeCata<_> = g.into();
503 assert_eq!(tree_cata.each_root(empty(), map, fold), [
504 "(( 3 )( 4 )( 5 ) 1 )( 2 )",
505 "( 3 )( 4 )(( 2 ) 0 )( 5 )",
506 "((( 3 )( 4 )( 5 ) 1 ) 0 )",
507 "((( 2 ) 0 )( 4 )( 5 ) 1 )",
508 "((( 2 ) 0 )( 3 )( 5 ) 1 )",
509 "((( 2 ) 0 )( 3 )( 4 ) 1 )",
510 ]);
511
512 // rightmost
513 let g = vec![
514 vec![(1, 0), (2, 0)],
515 vec![(3, 1), (4, 1), (5, 1), (0, 1)],
516 vec![(0, 2)],
517 vec![(1, 3)],
518 vec![(1, 4)],
519 vec![(1, 5)],
520 ];
521
522 let tree_cata: TreeCata<_> = g.into();
523 assert_eq!(tree_cata.each_root(empty(), map, fold), [
524 "(( 3 )( 4 )( 5 ) 1 )( 2 )",
525 "( 3 )( 4 )( 5 )(( 2 ) 0 )",
526 "((( 3 )( 4 )( 5 ) 1 ) 0 )",
527 "((( 2 ) 0 )( 4 )( 5 ) 1 )",
528 "((( 2 ) 0 )( 3 )( 5 ) 1 )",
529 "((( 2 ) 0 )( 3 )( 4 ) 1 )",
530 ]);
531}