(ブログ用)codeforces #400 d. the door problem
TRANSCRIPT
Codeforces #400D. The Door
Problemsatanic @satanic0258
🔓🔒🔓
A B C
以下の例(サンプル2)を例にとって解説していきます。なお今後、下の図において、・黒は未決定の状態・橙はオンにした状態・青はオフにした状態を表します。
a
c
b
🔓🔒🔓
A B C
まず A を押した場合、 A は全てのドアに繋がるため、全てのドアの状態が反転します。
a
c
b初期状態
🔒🔓🔒
A B C
まず A を押した場合、 A は全てのドアに繋がるため、全てのドアの状態が反転します。
a
c
b初期状態
🔒🔓🔒
A B C
まず A を押した場合、 A は全てのドアに繋がるため、全てのドアの状態が反転します。すると、 a はオフになってしまいました。a をオンにするには C もオンである必要があります。
a
c
b初期状態
🔒🔓🔒
A B C
まず A を押した場合、 A は全てのドアに繋がるため、全てのドアの状態が反転します。すると、 a はオフになってしまいました。a をオンにするには C もオンである必要があります。C をオンにしました。それに伴って、ドアの状態は…
a
c
b初期状態
🔓🔓🔓
A B C
まず A を押した場合、 A は全てのドアに繋がるため、全てのドアの状態が反転します。すると、 a はオフになってしまいました。a をオンにするには C もオンである必要があります。C をオンにしました。それに伴って、ドアの状態は次のようになります。
a
c
b初期状態
🔓🔓🔓
A B C
今、考慮していない c の状態も変わりましたが、結果的に c も開いている状態になったのでよしとします。
a
c
b初期状態
🔓🔓🔓
A B C
これで、全てのドアが開いている状態になりました。B の状態がまだ決まっていませんが、b は片方が決まっていて開いているため、b に繋がっている B はオフとなります。
a
c
b初期状態
🔓🔓🔓
A B C
これで、全てのドアが開いている状態になりました。B の状態がまだ決まっていませんが、b は片方が決まっていて開いているため、b に繋がっている B はオフとなります。よって、ドアを全て開いた状態にするスイッチの組み合わせがあることが分かりました。
a
c
b初期状態
この問題を、グラフ上で解いてみましょう。
初期状態
この問題を、グラフ上で解いてみましょう。2-SAT をグラフに帰着するとき、オン / オフの状態を決めるものそれぞれについて、オンの頂点とオフの頂点を作ります。
初期状態A
A
B
B
C
C
この問題を、グラフ上で解いてみましょう。2-SAT をグラフに帰着するとき、オン / オフの状態を決めるものそれぞれについて、オンの頂点とオフの頂点を作ります。ここで、オンの頂点はそのまま、オフの頂点には上にバーを付けることにします。
初期状態A
A
B
B
C
C
オン→オフ→
では、このグラフに辺を張っていきます。
初期状態A
A
B
B
C
C
オン→オフ→
では、このグラフに辺を張っていきます。まず A をオンにすると、 a,c を介して繋がる C もオンにする必要がありました。そのため、 A→C と辺を張ります。
初期状態A
A
B
B
C
C
オン→オフ→
では、このグラフに辺を張っていきます。まず A をオンにすると、 a,c を介して繋がる C もオンにする必要がありました。そのため、 A→C と辺を張ります。また、 b を介して繋がる B はオフにする必要がありました。そのため、 A→B と辺を張ります。
初期状態A
A
B
B
C
C
オン→オフ→
同様に、各頂点について辺を張っていきます。
初期状態A
A
B
B
C
C
オン→オフ→
同様に、各頂点について辺を張っていきます。B をオンにすると、 A はオフにする必要があります。従って、 B→A と辺を張ります。
初期状態A
A
B
B
C
C
オン→オフ→
同様に、各頂点について辺を張っていきます。B をオンにすると、 A はオフにする必要があります。従って、 B→A と辺を張ります。C をオンにすると、 A はオンにする必要があります。しかし、これについては既に調べてあるため、わざわざ二重に辺を張る必要はありません。
初期状態A
A
B
B
C
C
オン→オフ→
A をオフにすると、 C もオフにする必要があります。従って、 A→C と辺を張ります。
初期状態A
A
B
B
C
C
オン→オフ→
A をオフにすると、 C もオフにする必要があります。従って、 A→C と辺を張ります。B をオフにした場合、 C をオフにした場合については、既に調べられている状態になっているため、グラフ上に変化はありません。
初期状態A
A
B
B
C
C
オン→オフ→
こうして全ての辺を張ることが出来ました。
初期状態A
A
B
B
C
C
オン→オフ→
こうして全ての辺を張ることが出来ました。このグラフを見ると、つじつまが合うようなスイッチの組み合わせは全て同じ連結成分になっており、逆に矛盾が発生するような頂点同士は連結になっていないことが分かります。
初期状態A
A
B
B
C
C
オン→オフ→
こうして全ての辺を張ることが出来ました。このグラフを見ると、つじつまが合うようなスイッチの組み合わせは全て同じ連結成分になっており、逆に矛盾が発生するような頂点同士は連結になっていないことが分かります。では、ある頂点と連結になっている頂点を全て抜き出せばそれが正しい組み合わせとなるのでしょうか?
初期状態A
A
B
B
C
C
オン→オフ→
そうとは限りません。右の図のように、連結成分の中には「 A がオンならば A をオフにしなければならない」といったおかしな部分が出ることがあります。
初期状態
A
A
A
A
B
B
C
C
オン→オフ→
そうとは限りません。右の図のように、連結成分の中には「 A がオンならば A をオフにしなければならない」といったおかしな部分が出ることがあります。逆に言えば、グラフにこのような矛盾が無ければ正しいスイッチの組み合わせがあるとわかります。
初期状態
A
A
A
A
B
B
C
C
オン→オフ→
今回の例では、 A と A 、 B と B 、 C と C 、と全ての頂点で、別々の連結成分に属していることが分かります。
初期状態A
A
B
B
C
C
オン→オフ→
今回の例では、 A と A 、 B と B 、 C と C 、と全ての頂点で、別々の連結成分に属していることが分かります。よって、グラフからこの例では正しいスイッチの組み合わせが存在することが分かりました。
初期状態A
A
B
B
C
C
オン→オフ→
🔓🔒🔓
AB
C
では、今度は以下の例(サンプル1)について見ていきます。
a
c
b初期状態
では、今度は以下の例(サンプル1)について見ていきます。スイッチ数は先ほどと同じなため、グラフの初期状態も同じとなります。
初期状態A
A
B
B
C
C
オン→オフ→
まず A をオンにした場合について考えます。A は a を介して B に、また c を介して C に繋がっています。
初期状態A
A
B
B
C
C
オン→オフ→
まず A をオンにした場合について考えます。A は a を介して B に、また c を介して C に繋がっています。従って、 A をオンにすると B と C もオンにする必要があるため、A→B 、 A→C と辺を張ります。
初期状態A
A
B
B
C
C
オン→オフ→
まず A をオンにした場合について考えます。A は a を介して B に、また c を介して C に繋がっています。従って、 A をオンにすると B と C もオンにする必要があるため、A→B 、 A→C と辺を張ります。同様に、 B をオンにすると A はオンに、 C はオフにする必要があるため、 B→A 、 B→C と辺を張ります。( A-B 間は既に辺が張ってあるため実際には張りません)
初期状態A
A
B
B
C
C
オン→オフ→
同様に、
初期状態A
A
B
B
C
C
オン→オフ→
同様に、 C 、
初期状態A
A
B
B
C
C
オン→オフ→
同様に、 C 、 A 、
初期状態A
A
B
B
C
C
オン→オフ→
同様に、 C 、 A 、 B 、
初期状態A
A
B
B
C
C
オン→オフ→
同様に、 C 、 A 、 B 、 C についても辺を張ります。
初期状態A
A
B
B
C
C
オン→オフ→
同様に、 C 、 A 、 B 、 C についても辺を張ります。こうして、全ての辺を張ることが出来ました。では、どの頂点が連結になっているでしょうか。
初期状態A
A
B
B
C
C
オン→オフ→
同様に、 C 、 A 、 B 、 C についても辺を張ります。こうして、全ての辺を張ることが出来ました。では、どの頂点が連結になっているでしょうか。ある頂点から初めて辺を順に辿っていくと分かりますが、この例では、全ての頂点が連結となっています。
初期状態A
A
B
B
C
C
オン→オフ→
特に、 A と A が同じ連結成分に属しているため、この例では正しいスイッチの組み合わせが存在しないことが分かります。
初期状態A
A
B
B
C
C
オン→オフ→
特に、 A と A が同じ連結成分に属しているため、この例では正しいスイッチの組み合わせが存在しないことが分かります。このように、グラフに帰着してこの問題を解くことが出来ます。
初期状態A
A
B
B
C
C
オン→オフ→
実際にプログラムを実装する際には、・グラフに辺を追加する・ある2頂点が連結であるかを調べるというクエリをこなすデータ構造である、素集合森(通称 Union-Find )を使うと良いでしょう。
初期状態A
A
B
B
C
C
オン→オフ→
その後、 A と A が同じ連結成分に属しているか否かを調べることで組み合わせの存在を調べます。
※ 注意※しかし、この問題で現れる論理式は、・同値 ( ⇔ )…両方押すか押さないか・排他的論理和( XOR )…どちらか片方だけ押すの積となっています。
おわり