目次

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

パナソニックグループ プログラミングコンテスト2024(AtCoder Beginner Contest 354)

G - Select Strings

G - Select Strings

問題

解法1

やりたいことは、同時に選べない $i,j$ 間に辺を張ったグラフにおける 重み付き最大独立集合だが、一般的な解法はNP困難(NP完全?)とされている。

今回は、辺を有向(含む方→含まれる方)にした場合、「DAGである」 「$i→j,j→k$ に辺があれば、$i→k$ にも必ず辺がある(推移律)」という性質がある。
この場合は、Dilworthの定理を使えば解ける。

※ $S_i$ に全く同じ文字列が含まれる場合はDAGとは限らなくなるが、 $S_i$ が同じ同士では $A_i$ が最大のものを残して削除するなどの前処理をすればよい。

Dilworthの定理によると、

最大独立集合はNP完全だが、最小パス被覆は二部グラフの最大マッチング問題に変換できて解ける。

今回の場合は単なる最大独立集合ではなく、$A_i$ による重み付きだが、 これは二部マッチングを最大流で解くときの辺の容量を調整すればよい。

これで、$\sum A_i - \rm{MaxFlow}(S→T)$ が答えとなる。

Python3

解法2

0-1整数計画問題として扱える。

こういった問題はソルバを使える。

AtCoderのPythonで使えるソルバライブラリには、PuLP、OR-Tools、scipy.optimize、z3-solver などがある。

PuLPで解かせてみたところ、ほとんどは高速に解けるが、2ケースでTLEとなった。
(提出一覧には一部通っている提出もあるが、記事執筆時点では、PuLPで通している提出は時間のかかるケースを例外処理していたりする)

一方、OR-Toolsでは、特に例外処理せずとも全てのケースを高速に(200ms以内で)通すことができた。

また、scipyで通している例も見られた。

具体的に中身で何をやってるか不勉強にして分かっていないのだが、ソルバによっても得手不得手があるらしい。
AtCoderのPuLPで使えるソルバはCBC(COIN-OR Brand-and-Cut)のみだが、 今回はこれで時間がかかってしまうテストケースが含まれていたのかもしれない。

(生成AI使って競プロするのがどうのこうのという話がたまに話題になるが、 中身分かってなくても汎用的に使えてしまうという意味ではソルバも大概だな) 2)

Python3

1)
本当はもう少し抽象的な条件らしい。上記リンク先参照
2)
ただし、現状どのソルバもfloat型で演算されるので、53bit程度で表現できない値が答えになり得るようにすれば割と簡単にシャットアウトできる?