D - 覚醒ノ高橋君 解説 by maspy


読解から少し大変ですが,結局次の問題です:

  • \(A\) 個のグラフが与えられる.それぞれ \(D=7\) 頂点以下である.辺には除去するためのコストが定まっている.これらをすべて木にするときのコストについて,小さい方から \(K\) 番目のものを求めよ.

以下の手順で解くことができます.

(1) 各町について,コストが \(0\), \(1\), \(\ldots\) であるような辺の除去方法を数える.

(2) 町全体で見たときに,コストが \(0, 1, \ldots\) であるような辺の除去方法を数える.

(3) \(K\) 番目のコストを出力する.


(3) は容易です.(1) の前提のもと (2) を解くことも,基本的な dp でできます(畳み込みの形になりますが,特別な高速化は要求されません).

(1) は,すべての部分木を列挙すればよいです.例えば次のような方法があります.

  • dfs で順に辺を残すか消すかを決めていく.その都度 unionfind などで連結性を確かめて,残す辺がサイクルを作らないようにする.

  • \(D\) 頂点のラベル付き木は全部で \(D^{D-2}\) 通りあることが知られており,これをすべて列挙する.例えばこの数え上げの証明に用いられる Prufer Code を使ってすべてのラベル付き木を生成する.

計算量は以下の通りです.

  • 木の列挙:全体で\(O(A D^{D-2}\cdot poly(D))\)のような計算量.\(poly(D)\) は実装次第ですが, \(1\) からに \(D^3\) 程度になるのが普通だと思います.

  • 数え上げ:\(cost_i\) の上限を \(C\) とする.町ごとのコストは \([0, C\cdot (D-1)(D-2)/2]\) に収まる.すべての dp テーブルのマージが \(O(A^2C^2D^4)\) 時間でできる.

この計算量でも AC 可能です(テストケースが弱いため,見積もりよりもかなり高速に解けると思います).

数え上げパートは,次のような高速化手段もあります.

  • 「消す辺」のコストを考えると,町ごとのコストは \([0, C(D-1)]\) に収まり状態数が(\(D\) に関するオーダーレベルで)減る.
  • 畳み込みに FFT などを用いる.

投稿日時:
最終更新: