geam1113’s diary

主にAtcoderのコンテストの備忘録を書きます。AtCoder緑と水色を行ったり来たりしています。

AtCoder Biginner Contest 260 F - Find 4-cycle

コンテスト後に自力ACしましたが、記事を書いていて計算量の見積もりが誤っていたので、公式解説を読みました。

頂点集合U,Vを以下の通りとします。

U = \{1,\ 2,\ \cdots ,\ S\}
V = \{S+1,\ S+2,\ \cdots ,\ S+T\}

U,Vは独立集合であるという条件から、4-cycleをもつ条件は以下に限定されます。

Uに属するある頂点u_i,u_jと、Vに属するある頂点v_k,v_lであって、u_i,u_jのいずれもv_k,v_lの両方に辺がある

そこで、

  • Uに属する頂点u_iが、頂点Vに属する2つの頂点v_j, v_kの両方と辺を持つ

という場合に、それを

  • u_iが頂点対(v_i, v_j)を持つ

という風に表現したとき、4-cycleを探すという問題は、

  • Uから共通の頂点対を持つ2つを見つける

という問題に言い換えられます。

そこで、以下のような解法が考えられます。

i=1,\ 2,\ \cdots ,\ Sについて、以下を行う。

u_iと繋がる頂点をv_1,\ v_2,\ \cdots ,\ v_{m_i}とする。
ここから得られる全ての頂点対(v_j,v_k)について、u_iが持っているということを記録していく。ここで、既に別のu_xが、頂点対(v_j,v_k)を持っていた場合、(u_x,u_i,v_j,v_k)を答えとして出力する。

これでACしましたが、問題を解いた後に上記の部分の計算量の見積もりが誤りだったと気づきました。公式解説を見たところ、鳩の巣原理によりO(T^2)となることがわかりました。

これは、(v_i,v_j)という組は高々T^2個しかないので、頂点対を調べていくと、高々T^2 + 1回で既に一度調べた頂点対が現れる、ということです。

細かい実装の話に移りますが、C++で頂点対をpairとして、mapに記録する方法だとTLEしました。
二次元配列に記録していく方法だと、ACできました。配列として持てる場合は、mapは使用しない方が良さそうです。

Submission #33385373 - AtCoder Beginner Contest 260