最大クリーク問題で面白いなとおもったこと
いろいろ考えてるけど、最大クリーク問題は主に3つの関数からなる。
ある無向グラフGについてを最大クリークサイズを返す関数とする。
f(w) : 補グラフが非連結で、頂点がn個に分けられているとする、そのとき元の誘導部分グラフをとすると
g(m) : グラフが非連結で、連結グラフn個に分かれているとする、その各グラフをとすると
h(k) : 頂点をうまく分割するとサイズkのクリーク(はサイズkのクリークの集合)と、その全点から接続している頂点とそれ以外。
となるのが極大クリーク。
上記を踏まえ、判定式をつくる
f(w)のうち、補グラフで孤立点(元のグラフでは自身を除く全点と接続)となっているものを取り出す処理をp(n)とする。で処理できる。
h(k)はk=2に固定したとp(n)と畳み込み使って、下記のように表すことができる。
g(m)についてはが、Eを順次探索するのでその時に一緒にやってしまえる(実装では辺に対してBFS, クリークに対してDFSとなっている)のであまり考えなくてよい。f(w)の孤立点以外については実装は簡単(UnionFind)でできるけど、そのケースにどれくらい当てはまるかが微妙なのと補グラフの辺はもっていないので掛けてつくるかが微妙、濃度に合わせてやるのが良さそうという感じをもっている。
とりあえずABC002 派閥で試してhttp://abc002.contest.atcoder.jp/submissions/1271432はRubyでは最速になってた。C++と比べるとおそいけどスピンアップの時間考えるとかなり速いと思う。
Cのコード見てると隣接行列使って解いてるっぽいコードがあった。すげぇ早い
メモ: 下記の論文によると補グラフのBFSやDFSをでできるらしい。なら、やればよいかという気がしている。