2021年7月10日土曜日

CodeChef - Short in Average

AAからBBへのウォークが与えられたとする。このウォークが閉路を含んでいて閉路の平均長がウォークの平均長より小さいなら、何回も回ればウォークの平均長を閉路の平均長まで下げられるし、そうでないなら閉路を除いて損しない。また、閉路を含まないウォークは高々N1N-1本の辺しか含まない。従って、以下のようなアルゴリズムが考えられる:

  1. BBに到達できる頂点の集合WVW \subseteq Vを求めて、以降はWWによる誘導部分グラフ上で考える。
    • この時点でAABBがつながっていなければ終わり。
  2. Bellman-Ford法のようなDPをして、高々N1N-1辺を通るという条件の下でのAAからBBまでの最短平均長ウォークの長さを求める。
  3. AAから到達できる最短平均長閉路の長さを求める。
  4. 2と3の小さいほうを取る。

実装上は3のアルゴリズムが2のDPを含んでいる。2はN1N-1回、3はNN回回す必要があるので、最初からNN回回せばよい。

3については、dp[k][v]=\operatorname{dp}[k][v] =ちょうどkk本の辺を使う場合のSSからvvへの最短経路、として

L=minvNmaxk=0,...,N1dp[N][v]dp[k][v]Nk L = \min_{v \in N}\max_{k = 0, ..., N-1} \frac{\operatorname{dp}[N][v] - \operatorname{dp}[k][v]}{N-k}

が求める長さである。ただし、SSから到達できない頂点がある時にそのまま扱うと\infty - \inftyという計算が起きてしまうので、dp[N][v]=\operatorname{dp}[N][v] = \inftyの場合は除いて計算する。全部そう(=NN回目で到達できる頂点がない)なら閉路がないグラフなのでL=L = \inftyになるべきで、つじつまがあっている。

解説は「平均長がLL以下のウォークが存在するか?」という判定問題を解いて二分探索する方針だった。判定問題は、すべての辺の重みからLLを引いた時にSSからTTへの長さ00以下のウォークが存在するかどうかで判定できて、これはやはりBellman-Fordで調べられる。