めもめも

このブログに記載の内容は個人の見解であり、必ずしも所属組織の立場、戦略、意見を代表するものではありません。

003 - Longest Circular Road(★4)の解説

何の話かと言うと

atcoder.jp

「トポロジカルオーダーで処理する」系の問題例としてこちらを紹介します。

この問題では、無向グラフを取り扱います。有向グラフの例については、下記の記事が参考になります。

enakai00.hatenablog.com

考え方

ノード数 N に対してリンク数が N-1 であることから、木構造のグラフだと気づきます。(気づいてください。)そこで、始ノードを見つけて、一歩づつ歩きながら歩数をカウントしていきます。ノード n に対して dp[n] をそのノードに至るまでの歩数の最大値として記録していきます。a -> b に進んだら、

dp[b] = max(dp[b], dp[a]+1)

というアップデートができます。この際、(アップデート前の値を用いて)、dp[b] + dp[a] + 1 は、ノード b で出会う2つの経路の距離を表す事に注意します。

たとえば、a -- b -- c という経路で、c -> b (dp[b] = 1 になる)というアップデートの後、a -> b というアップデートをすると、既存の dp[b] は c からの距離になるので、dp[b] + dp[a] + 1 は、(b で出会う)a と c の距離になります。

この問題では、このような経路の距離の最大値を求めればよいので、一歩進む度に dp[b] + dp[a] + 1 を計算して、その時点の最大値を保持していけばOKです。

最後に残った最大値に(閉路にするために追加する道路分の)1 を加えたものが答えになります。

atcoder.jp

おまけ

この記事では「トポロジカルオーダーで処理する」系の問題として解きましたが、これは、一般には、「木の直径を求める」という問題で、公式解説では、一般的に知られたエレガント(?)な解法も紹介されています。

github.com