Skip to main content

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}