web-dev-qa-db-ja.com

このグラフで最短経路を見つけるには、どのアルゴリズムを使用すればよいですか?

約10億個の頂点を持つグラフがあり、それぞれがランダムに他の約100個の頂点に接続されています。

2点間の最短経路のlengthを検索したい。使用される実際のパスは気にしません。

ノート:

  • エッジが切断または追加されることがあります。これは、ルックアップの約500分の1の頻度で発生します。パフォーマンスを向上させることができるのであれば、エッジ変更をバッチ処理することもできます。
  • グラフを前処理できます。
  • 6ステップ以上かかる場合は、無限に戻ることができます。
  • 0.01%の確率で間違っていても問題ありませんが、長すぎる長さを返す場合のみです。
  • すべてのエッジの長さは1です。
  • すべてのエッジは双方向です。

アルゴリズムを探しています。 Psuedocode、英語の説明、実際のコードはすべて素晴らしいです。

A *を使用することもできますが、パスファインディング用に最適化されているようです。
Dijkstraのアルゴリズム を使用することを考えましたが、すべての頂点の最短パス検出属性を無限大に設定する必要があるステップがあります

(ユースケースについて疑問がある場合は、アンダーハンドCコンテスト用です。)

8
Nick ODell

基本アルゴリズム

開始ノードと終了ノードから到達できるノードの2つのセットを維持します。交互に、両側から3ステップ進みます。セットをノードに置き換えるたびに、もう1つのステップで到達できます。各ステップの後、2つのセットの共通ノードをチェックします。

最適化

単一のスイープで一般的なノードを検索できるように、セットをソートされたとおりに反復できることを確認してください:O(n + m)操作。リストはそれぞれ最大100万ノードになります。

セットを1ステップで拡張するには、元のセットのノードのすべての接続をクエリし、それらを新しいソート済みセットにマージします。ソートされた2つのリストのマージは、1回のスイープで再度実行できます。したがって、ソートされたノードの接続を照会できることを確認する必要もあります。 (これは前処理される可能性があります)。

最後の2つのステップでは、新しい各セットは、これらのクエリ結果の最大10000をマージした結果です。このマージアダプティブ(同じサイズのチャンクをマージ)を行うのが最善です。このようにして、ソートされたセットのデータ構造は、単純なリンクリストにすることができます。

このようにして、アルゴリズム全体がO(6 * n + 6 * n * log n)になります。ここで、nは最大です。 1,000,000。

6
Kris Van Bael

ブレスファースト検索を使用してください(すべてのエッジが均一な長さなのでダイクストラのアルゴリズムは必要ありません)(そして、クリスヴァンバエルが言ったように、両側から実行してください)。

2
user470365

"All edges have a length of 1"これは Dijkstra's Algorithm を完全な貪欲なアルゴリズムの選択にする最良のシナリオです。高速行列乗算を含む Floyd-Warshallアルゴリズム を使用しても、うまく機能します。

0
Mushy