Problem I : Linear Ether Geometry 問題作成・英訳:三廻部 担当: 福澤 菅原 野田 解説: 福澤 野田 問題 書斎1 書斎2 インターネット・コネクタ 書斎3 書斎4 書斎5 各書斎へのコネクタ • 廊下の端にあるインターネットコネクタと各書斎のコ ネクタをハブとケーブルを使って接続したい. • ハブをできる限り少なく,ケーブルのたるみの合計 をできる限り小さくしたい. • 書斎数 ≦ 5, ケーブル数 ≦ 10, 廊下の長さ ≦ 20 • 使うハブの最小数と,ハブが最小数のときのケーブ ルのたるみの合計の最小値を出力せよ. 注意 • 間違ってもナイーブな探索はしてはいけない O(2^L * M!) ≒ 3,805,072,588,800 解法(1-1) • シュタイナー木のDPの応用+初期化による枝刈り • シュタイナー木: グラフGとGの頂点部分集合Tが与えられたとき, Gの部分グラフでTを全て張る木 など – シュタイナー木問題: 最小のシュタイナー木を求める問題.NP困難 – シュタイナー木問題の解法 • Dreyfus-Wagner • Robins-Zelikovsky 解法(1-2) • シュタイナー木のDPの応用 – ある座標にハブを置いたとして, そのハブ以下に,あるケーブルの組合せだけで, ある書斎の組合せを,接続する際に 使うケーブルの最小数と, そのときのたるみの合計の最小値を探索で求める – ケーブルを一本選んで,そのケーブルを使ってイン ターネットコネクタと接続可能な全ての座標にハブを 置いてみて探索開始 – ケーブルの最小数 – 書斎の数 = ハブの最小数 解法(1-3) • 各状態は, 以下の二通りの探索で最小値を求める – 書斎の組合せを二つに分け,それに合わせて ケーブルの組合せも二つに分ける – ケーブルを一本選んで,そのケーブルを使ってお ける場所に一つハブを設置し,書斎と残りのケー ブルをまるごと移動 解法(1-4) • 初期化による枝刈り – 書斎数 > ケーブルの数ならImpossible – 書斎数 == 1 • ケーブルを全部使っても無理なら Impossible • ↑以外なら,もっともケーブルを使わずにもっともたるみの 合計が少ない長さを計算 – 書斎数 ≦ ケーブルの数 • ケーブルから短い順に書斎数 - 1本を抜いたケーブルの長 さの合計 < ハブから一番遠い書斎までの距離 なら Impossible • 現在のハブと各部屋それぞれ一本のケーブルで直接接続 できるとき,即計算可能 • 初期化で決定しなかった部分をmemoizeで探索 解法(1-5) • 注意点 – ハブの数が0の場合もある – やってはダメな枝刈り • ハブの座標が単調増加 など – ナイーブに書くと,TLEになる可能性大 • ソースコード:200行(6,105バイト) • 製作期間:合計3週間くらい • ジャッジ入力実行時間: C++ 15.0sec, Java 37.3sec 解法(2-1) • HUBの設置位置の組合せを探索 • 設置位置の各組合せについて、どの接続に どのケーブルを用いるか、二部グラフを作成 して最小費用流を用いて割り当てる 解法(2-2) • 最小費用流が分からない方はインターネット で検索して下さい – アジア地区予選では滅多に出ないので心配する 必要ありません 解法(2-3) • 前提 – HUB同士の接続は木構造である – 部屋からHUBへつなぐとき、どのHUBにつなげて も良い – インターネットコネクタからHUBにつなぐとき、どの HUBにつなげても良い 解法(2-4) • 最小費用流のグラフを作成する – Src→ケーブル – ケーブル→コネクタ-HUB間 – ケーブル→HUB間 – ケーブル→HUB-部屋間 – ***→sink 解法(2-5) • 左側(source側)にケーブルを配置する – 各ケーブルの種類についてノードを作成する – Srcからコスト0、流量がケーブルの本数である辺 を追加する 解法(2-6) • コネクタ-HUB間の接続に使用するケーブルの 候補を表す辺を追加する – HUB同士は木構造で接続されているので、どれ につないでも良い – 各ケーブルについて最もたるみが少なく接続でき るHUBを選び、コストをたるみ、流量を1とした辺を 追加する 解法(2-7) • HUB間の接続に使用するケーブルの候補を 表す辺を追加する – 各HUBに番号をつける – 自分の番号より小さい番号のHUBにつなげれば、 自然と最適な木構造になるはず • 反例がある • これについては後述する 解法(2-8) • 各ケーブルについて最もたるみが少なく接続 できるHUBを探し、ケーブルからHUBのノード へ、コストがたるみ、流量が1となる辺を追加 する 解法(2-9) • HUB-部屋間の接続に使用するケーブルの候 補を表す辺を追加する – 各部屋からはどのHUBにつないでも良い – 各ケーブルと部屋の組について、最もたるみなく つなげるHUBについて、コストをたるみ、流量を1 とした辺を追加する 解法(2-10) • コネクタ-HUB間、HUB間、HUB-部屋間を表す ノードからsinkにコスト0、流量1の辺を追加す る 解法(2-11) • HUB数+部屋数のフローが流れれば、そのコ ストが、そのHUBの配置でのたるみの最小と なる 解法(2-12) • 一部のHUBの木構造を再現できない – 最小費用流の実行後に木構造を再構築すること で、一応最適解を求めることができる • あくまで撃墜困難というだけ • 証明はしていない – 例) 解法(2-13) • 木構造の再構築 – グラフの連結を維持したまま たるみをより少なく できか各枝について調べていき、枝をつなぎかえ る 解法(2-14) • HUBの位置の探索を行う – HUBの数が小さいほうから全ての組合せを試す – ただし枝狩りをがんばる 解法(2-15) • 枝狩り条件 – 現在のHUBの配置では最後の部屋までケーブル が届かない場合 – 一番長いケーブルを使っても一つ前に配置した HUBに接続できない場合 – 探索中のHUBの配置で部分マッチンググラフを作 成し、フローが流れなかった場合 – マッチングの直前、フローが流れないことが明ら かな場合 解法(2-16) • ソースコード : 587行 18kバイト • 製作期間 : 約2週間 • ジャッジ入力実行時間 – 32.7sec – 特定の入力に対し劇的に遅い • ランダム入力は一瞬で終わる 注意 • HUBがインターネットコネクタと同じ場所に配 置される場合がある • HUBを必要としない場合がある 結果 • • • • Submit数 : 1 Accepted数 : 0 First Submit : 243分(iromono) ? First Accepted : なし iromonoのソースコード #include <iostream> int main() { oflakjds;flajsf;lsajdf;lj; } なにやってんの? 宿題 • 解法2を撃墜せよ
© Copyright 2024 ExpyDoc