CodeChef July Challenge 2018: Tom and Jerry
CodeChef July Challenge 2018の問題: Tom and Jerry (Code: JELLYTOM)
問題ページ: https://www.codechef.com/JULY18A/problems/JERRYTOM
問題概要
Jerryを捕まえるためにTomは匹の猫を雇う。
そして、つの頂点と本の辺を持つグラフ上で匹の猫達がJerryを捕まえようとする。
このグラフは以下の特徴を持つ
- 4つ以上の頂点からなる単純閉路について、この中に含まれる頂点同士を結ぶ、閉路に含まれない辺が存在する
このグラフ上では、各roundで以下の手順を行う
- 最初のround 0では、猫達は最初にとどまる頂点集合となるを選択し、Jerryはとどまる頂点を選択する
- 各round では、にいる猫達とにいるJerryが以下のように移動する
- 猫達が次にとどまる頂点集合を選択し移動する
- その後にJerryは、に含まれる頂点を通らないパスで到達できる頂点に移動し、そのような頂点が存在しない場合はJerryは捕まる
グラフ上でJerryを捕まえるために必要な最小の猫の数はいくらか?
制約
1つのテストケースに含まれるケース数: (の制約においては)
多重辺は存在しない
解法
この問題は、グラフの最大クリークのサイズが解になる。
問題文中の特徴を持つグラフはChordal graphらしく、一般的なグラフに対してNP困難である最大クリーク問題が多項式時間で解ける(perfect elimination ordering等が利用できる)。
コンテスト中の思考
はグラフの最大クリークのサイズ以上でなければならないことは分かった。そうでなければ、グラフの最大クリーク上でJerryに逃げ続けられることになる。
例えば、下の図のグラフは最大クリークのサイズが5であるが、が4以下の場合は頂点3,4,5,6,7上でJerryが逃げ続けることができる。
これより解が最大クリークのサイズ以上であることは分かるが、最大クリークのサイズが解になる根拠がなかったため、いくつか実験して正しそうだったので出したら通った。
解説メモ
Forumのdiscussionに説明が載ってたので、ここにメモ。
まず、今回の問題はvisible cops and robbers gameというGraph searching gameの形そのままらしい。(参考pdfに載ってる)
そして、このゲームでsearchers(問題分中の猫達)がfugitive(問題文中のJerry)を捕まえるためには((グラフのtreewitdh)+1)人が必要であることが示されており、Chordal graphにおけるtreewidthは(最大クリークのサイズ)-1と等しいことから解は最大クリークのサイズになる、ということらしい。
実装
Bron–Kerbosch algorithmで極大クリークを列挙しながらを求めた。
提出コード (PyPy2): https://www.codechef.com/viewsolution/19209051
T = int(raw_input()) for _ in xrange(T): N, M = map(int, raw_input().split()) G = [set() for i in xrange(N)] D = [0]*N for i in xrange(M): u, v = map(int, raw_input().split()) G[u-1].add(v-1) G[v-1].add(u-1) D[u-1] += 1; D[v-1] += 1 # Bron-Kerbosch algorithm def rec(V, P, X): if not P and not X: return V r = V; u = None if X: u = next(iter(X)) else: u = next(iter(P)) for v in P - G[u]: r0 = rec(V | {v}, P & G[v], X & G[v]) if len(r) < len(r0): r = r0 P.remove(v) X.add(v) return r I = range(N) I.sort(key=lambda x: -D[x]) ans = 0 P = set(range(N)) X = set() for v in I: r = rec({v}, P & G[v], X & G[v]) P.remove(v) X.add(v) ans = max(ans, len(r)) print(ans)