Processing math: 100%

パナソニックグループ プログラミングコンテスト2024(AtCoder Beginner Contest 375)E,F,G問題メモ

E - 3 Team Division

問題文

  • N 個の整数が 3 つのグループ 1,2,3 に分かれています。
    • i 個目の整数は Bi で、グループ Ai に属しています。
  • 0 個以上の要素が属するグループを変更することで、すべてのグループの総和が等しくなるようにできるか判定してください。また、すべてのグループの総和が等しくなるようにできる場合は、属するグループを変更する要素の個数として考えられる最小値を求めてください。
  • ただし、グループ 1,2,3 の他に新たにグループを作ることはできません。

制約

  • 3N100
  • Ai{1,2,3}
  • x{1,2,3} に対し、ある i が存在して Ai=x
  • 1Bi
  • Ni=1Bi1500
  • 入力される値はすべて整数

解法

以下は(たぶん)嘘解法で、TLEするケースが作れてしまいそう。

全要素の和が3の倍数で無い場合は不可能。以下、3の倍数とし、1グループ当たりの目標値 T=Bi3 とする。

12,13,21,23 の4つの移籍する要素の合計値を固定すると、31,32T との関係性から自動的に決まる。

  • Ci[j,k]:= グループ i から一方へ合計 j、もう一方へ合計 k の要素を移籍するときの最小個数
    • 不可能な場合はINF

i=13 に対し前計算し、4つを全探索する。

そのままだと最悪 (15004)42×1010 くらいかかるが、

  • 移籍する要素の合計値(Ci[j,k] に対する有効な (j,k) の個数)の取り得るパターン数の少ない2グループを探索する
  • Ci[j,k] の値が小さい方から探索し、途中で暫定最小値を上回ったら打ち切る

など小手先の高速化をすると、間に合う。

Python3

ちゃんとした解法

  • DP[i,j,k]:=i 個目の要素まで見て、グループ1の合計 j、2の合計 k である時の移籍人数の最小値

i,j,k からグループ3の合計は自動的に決まるので、DPとしては持たなくてよい。
また、j,k の上限は「全要素の和/3 500」まで持てばよい。

python3

F - Road Blocked

問題文

  • AtCoder国には 1 から N の番号がついた N 個の都市と、1 から M の番号がついた M 本の道路があります。
  • 道路 i は都市 Ai と都市 Bi を双方向に結び長さは Ci です。
  • Q 個のクエリが与えられるので順に処理してください。クエリは以下の 2 種類のどちらかです。
  • 1 i:道路 i が通行止めとなる。
  • 2 x y:通行止めでない道路のみを通るときの都市 x から都市 y への最短距離を出力する。都市 x から都市 y に到達できないときは代わりに -1 を出力する。
  • なお、1 種類目のクエリはテストケースごとに 300 回以下であることが保証されます。

制約

  • 2N300
  • 0MN(N1)2
  • 1Ai<BiN
  • (Ai,Bi) は相異なる
  • 1Ci109
  • 1Q2×105
  • 1 種類目のクエリにおいて、1iM
  • 1 種類目のクエリにおいて与えられる道路は、その時点で通行止めでない
  • 1 種類目のクエリは 300 回以下である
  • 2 種類目のクエリにおいて、1x<yN
  • 入力は全て整数である

解法

Q の上限は 2×105 と大きいが、そのうちクエリ1は 300 回以下という意味ありげな条件が付いている。

N も小さいので、「クエリ1のたびに O(N2) くらいかけて全点間距離を再計算する」ことが可能ということ。

また、一般的にグラフを切るよりは繋ぐ方がやりやすいので、こういう問題は「クエリを逆順に見る」が有効そう。

ということで、まずクエリで通行止めにならない辺のみを使って Froyd-Warshall で全点間距離 D(x,y) を求める。

クエリを逆順に処理する。

  • クエリ2の場合、単に D(x,y) を参照する
  • クエリ1の場合、D を更新する。
    • コスト c の辺 (a,b) が加わることで、2点間の距離 D(x,y) は以下の最小値に更新される。
      • 追加辺を使用しない D(x,y)
      • xaby の順に通過する D(x,a)+c+D(b,y)
      • xbay の順に通過する D(x,b)+c+D(a,y)
    • これを、全 (x,y) に対して計算する。

Python3

G - Road Blocked 2

問題文

  • AtCoder国には 1 から N の番号がついた N 個の都市と、1 から M の番号がついた M 本の道路があります。
  • 道路 i は都市 Ai と都市 Bi を双方向に結び長さは Ci です。
  • i=1,,M について、以下の 2 つの値が異なるかどうか判定してください。
    • 全ての道路が通行可能なときの、都市 1 から都市 N への最短距離
    • 道路 i 以外の M1 本の道路が通行可能なときの、都市 1 から都市 N への最短距離
  • 異なる場合はYes、同じ場合はNoを出力してください。
  • ただし、一方では都市 1 から都市 N に到達可能で、他方では到達不可能なとき、両者の値は異なるとみなします。

制約

  • 2N2×105
  • 1M2×105
  • 1Ai<BiN
  • (Ai,Bi) は相異なる
  • 1Ci109
  • 全ての道路が通行可能なとき、都市 1 から都市 N へは到達可能
  • 入力は全ては整数である

解法

F問題とテーマは似ている。

とりあえず、最短経路に使われ得る辺しかYesになり得ないので、そういう辺を特定したい。

仮に、Dijkstraの結果から「最短経路を1つ」復元するときは、 各頂点 v に対して最短経路における前の頂点のうちの1つ(predecessor)Pv を 経路探索中に記録しておくと、PN から辿ることで復元できる。

今回は、「全ての最短経路に含まれる辺」を特定したいので、Pv をリストにし、 同じ最短距離で v に辿り着ける前頂点を全て記録しておくと、同様に復元できる。
Pv のリストの要素の1つを u とすると、(u,v) が1辺に対応するので、全リストの要素数は辺数 M で抑えられる)

この「最短経路に含まれる辺」のみからなるグラフから「橋」を見つければ、それが Yes となる辺となる。


※最短経路に含まれうる辺の判定は、以下のようにしてもできる。
頂点 1 からと N からDijkstraしておく。
コスト c の辺 (u,v) について、D(1,u)+c+D(v,N)=D(1,N)(または u,v 入れ替えたもの)が成立するなら、 その辺は最短経路に含まれる。

Python3

解法2

橋を使わなくても求められる。こっちの方が思いつけば簡単。

頂点 1N からそれぞれ、「最短距離 D」および「最短距離を実現する経路数 C」を求める。

各辺 (u,v,c) につき、最短経路に使われるかの判定を行う。これは前の解法の末尾に※で記した補足と同じ。

  • D(1,u)+c+D(v,N)=D(1,N) なら最短経路に含まれる

最短経路に使われる辺に対し、この辺を通る以外に最短経路がない事を調べるには、以下のようにすれば良い。

  • C(1,u)×C(v,N)=C(1,N) なら、この辺を通る以外に最短経路はない

ただし C は非常に大きな数となり得るため、適当にmodを取って管理する。

programming_algorithm/contest_history/atcoder/2024/1012_abc375.txt · 最終更新: 2024/12/13 by ikatakos
CC Attribution 4.0 International
Driven by DokuWiki Recent changes RSS feed Valid CSS Valid XHTML 1.0