2019年8月29日木曜日

CS Academy - Necromancer

CS Academy - Necromancer

複雑な設定だが、考えるべきは各投票者がどの候補者をトップ(一番目)にした可能性があるか、だけである。

与えられた投票者AAについて、AAの投票した候補者の部分列がq1,q2,...,qlq_1, q_2, ..., q_lであるとわかっているとする。ネクロマンサーの投票操作を最小で済ませるためには、候補者11にとって最善のケースを考えるべきである。q1=1q_1 = 1ならAAは候補者11をトップにしたと考えれば良いし、q1,q2,...,qlq_1, q_2, ..., q_lに候補者11が含まれていない場合もやはり候補者11をトップにしたと考えてよい。その他の場合、つまり部分列の中に11が含まれているが最初ではない場合、AA11以外の候補をトップにしたことになる。l=Kl = Kならそれはq1q_1だし、lKl \neq Kならq2,...,qlq_2, ..., q_l以外のいずれかの候補である。

さて、11以外に投票したことがわかっている候補者については、投票先を2,3,...,K2, 3, ..., Kにばらけさせて、得票数の最大値ができるだけ小さくなるようにしたい。その最小値がわかれば、ネクロマンサーはそれを超えるように候補者11の得票を増やせばよい。これは二分探索とフローで実現できる。つまり、得票数の最大値がある値DD以下にできるかどうかを最大フローで判定すればよい。

グラフの作り方としては、始点SSを(投票先が1以外の)各投票者と容量11の辺でつなぎ、投票者をありえる投票先に容量11の辺でつなぎ、(1以外の)各候補者と終点TTを容量DDの辺でつなげばよい。

サンプルのケースでは次のようなグラフになる:

Sample 1

3人の投票者v1,v2,v3v_1, v_2, v_3について、4人の候補者p1,p2,p3,p4p_1, p_2, p_3, p_4の中からありえる投票先につないでいる。何も書かれていない辺の容量は11である。候補者11は常に無視してよいし、投票者33も候補者11に投票しているとみなせるので無視してよいが、便宜上、図に書いている。
このグラフに流量22=S=Sから出ている辺の容量の合計)のフローが流せれば、得票数の最大値がDD以下にできることがわかるので、二分探索で境界を探せば良い。