輪郭をなぞるだけのブログ

浅学菲才のためにおそらく嘘も多い

全方位木 DP の抽象化

全方位木 DP の抽象化を書いてみた。
コードと使用例のみ。(使用例はネタバレあり)

気が向いたら解説を書くかもしれない、未来の自分に期待。
少しだけ書くと、rerooting_function では、子ノードの subtree_dp の累積を両側から取って、それぞれの子ノードに対して rerooting_dp を求めるということをしている。
( 2021/02/16 修正 : E - 限界集落 のように辺に向きがある場合に困ったので、子ノードに根方向の部分木の情報を伝播させて、ノードに訪れたときに rerooting_dp を更新するように変更。また、重み付きの方に有向辺を入れる関数も追加。)
最後の参考文献に上げたリンク先を参照すると分かりやすいかもしれない。
このような実装が不必要な場合もあるが、使用例の問題のように割り算ができない場合にも対応するためにもこの実装にした。

あまり多くの問題を見てないので、抽象化がこれでいいのか分からない。
適宜訂正していく可能性が大いにある。
※頂点重み付きも追加 (2021/04/04)

コード

重みなし

重み付き

頂点重み付き

使用例 (ネタバレ注意)

重みなし

atcoder.jp

重み付き

http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=1595
木の直径を求める。
2 回 DFS すればできるが、全方位木 DP でやってみる。

頂点重み付き

codeforces.com

雑記

全方位木 DP しばらく書かずにいるとバグらせがちなので、ライブラリにしてみた。
ただ、ライブラリを書き上げてから、もっと他にやるべきことがあるだろ?暇人かよ、という気持ちになり悲しくなった。

こういうのは GitHub に上げるのがいいのだろうか。

コードを見れば分かるのだが、効率の悪いことをしている。
自分は高速化にそこまで興味がないので放置してしまっているが、直してくれる誰かに期待......