Moon
- 2. 問題概要
● ツリー状の飛行路を使って地球から月へ
行く
● 移動できる距離の上限Mが決まっている
● できるだけ多くの頂点をたどりたい
- 3. 分かること
● 最終的には必ず月に到着する
→地球から月へのパスは必ず通る
→最終的な経路はこのパスを含む部分木
になっている
- 6. 方針
● 一旦地球から月へのパスのことを忘れる
と、求めるのは辺のコストの合計がM以下
である部分木のうち頂点数が最大のもの
● 頂点数が最大→同じ頂点数の時コストが最
小
● よって
dp[v][i]:頂点vを根とし、頂点数がiである部
分木のうちコストの合計の最小値
を考え、下の方の頂点からdpテーブルを
マージしていけばよい
- 7. 方針
● 頂点vを親としたとき、ある子uで頂点をi個
使い、他の子と親で合計頂点をj個使うとす
ると
dp[v][i+j]=min(dp[v][i+j],
dp[u][i]+dp[v][j]+cost* 2)
● これを辺の数(n+1)回行い、i<=n+2,j<=n+2
なので計算量がO(n^3)になってやばそう?
- 8. 計算量
● 検証してみる
● サイズxの部分木のdpテーブルを作るの
に必要な計算量をf(x)とする
● サイズa、bの部分木を作り、それらを
くっつけてサイズa+bを作る時の計算量
は
f(a+b) = f(a) + f(b) + ab
● ここで明らかにf(1) = 1
- 9. 計算量
● 帰納法を用いる
● f(x) ≦ x^2 を仮定したとき、
f(a+b) = f(a) + f(b) + ab ≦ a^2 + b^2 + ab
≦ (a+b)^2
● これと f(1) ≦ 1^2 より f(x) ≦ x^2 が成り
立つ
● よって計算量はO(n^2)となり、十分間に
合う!
- 10. 実装例
● 月を根としてDFSしながらdpテーブルを
更新していく
– DFSの返り値にその下に地球があるか
どうかを持たせ、あればそのdpテーブ
ルを(頂点数を+1,コストを+(辺のコス
ト)して)コピー、なければ先ほどのよ
うに更新していく
● あらかじめ地球から月へのパスを一つの
頂点としてマージしておき、残りを普通
の木と同様にやるという方法もある
- 11. 注意点
● 辺のコストを足すとき×2を忘れないよう
に
(地球ー月間のパス以外)
● 頂点数はn+2
● 地球と月には餅屋はないので、答えは(頂
点数)-2
● 貪欲でいける!と思ってしまうと死にま
す(writer談)
- 12. ● First AC:nadeko
● Accept数:7
● Submission数: 37