feature image

2025年3月15日 | ブログ記事

Rust で変な木 DP を書いた

この記事は新歓ブログリレー 8 日目の記事です。

こんにちは、23B の @hayatroid です。普段は競プロなどしています。

突然ですが

以下のソースコードは木 DP の例題として知られる EDPC の P 問題 に対する私の提出ですが、どうやらおかしな部分があるようです。main 関数の中身を追っていくと、隣接リストを構築し、行きがけ順で探索し、そのまま ( 帰りがけ順で値を fold せずに ! ) 途中で終わっているように見えます。しかし AC は得られています。いったいどういうことでしょうか ( ソースコードの下に種明かしがあるので考えてみてください ) 。

種明かし

正解は……

でした !

( よくわからないという声が聞こえてきたので、以下に詳しい解説をです。)

drop とは

Rust には次のような所有権という概念があります ( the book を参照 ) 。

これにより、main 関数を抜けると、main 関数内の値が drop し、破棄処理が走ります。この破棄処理はオーバーライドでき、今回の例では子が破棄される際に、子から親に向かって値を fold する処理をねじ込んでいます ( 51 ~ 60 行目 ) 。

葉から順に drop させたい

上記の処理をしたとしても、それが葉から順に起こらないようでは、正しい結果が求まりません。

そもそも drop の順番をいじれるの ? というところではありますが、Rust の参照を使うとうまいことできそうです。参照は次のルールを満たします ( the book を参照、参照だけに ) 。

2 番目のルールはいわゆるダングリングポインタを防ぐためで、例えば A が B を参照しているとき、A が drop するより先に B が drop することはない、ということが保証されています。

これより、子が親を参照する形にすれば、親は 1 つでも子がいれば drop しないので、葉から順に drop することが保証されます。

ちなみに、複数の子が 1 つの親の可変参照を持つことは 1 番目のルールによりできませんが、Rc<RefCell<親>> を持つことで似たようなことが実現可能です ( 27 行目 ) 。この辺りの解説は the book などに委ねます。

まとめると

全体としては以下のような処理を行っています。

処理のほとんどが main 関数外なのと、帰りがけ順で値を fold していく部分 ( drop する順番の決定 ) を Rust の所有権システムに委ねているのがこのプログラムの面白いポイントだと思います。

おわりに

実用性はなさそうです ( 泣 )

新歓ブログリレー、明日の担当は @beferia さんです ! お楽しみに !

hayatroid icon
この記事を書いた人
hayatroid

23B Rustで競技プログラミングをします

この記事をシェア

このエントリーをはてなブックマークに追加
共有

関連する記事

2025年3月9日
# WOLF RPGエディターについて
Synori icon Synori
2025年3月12日
サークル旅行のためだけにアプリをこしらえる人たち
kitsne icon kitsne
2025年3月7日
新歓特設ページを公開しました!【新歓ブログリレー1日目】
Luke256 icon Luke256
2025年3月13日
traPを吸い尽くせ! (traP活用法紹介)
zoi_dayo icon zoi_dayo
2025年3月11日
Raspberry Pi から SwitchBot(ボット)を操作してみる
SyntaxError icon SyntaxError
2025年3月10日
たのしく単位をとろう!
Naru820 icon Naru820
記事一覧 タグ一覧 Google アナリティクスについて 特定商取引法に基づく表記