web-dev-qa-db-ja.com

加重グラフにBFSを使用する

単一ソースの最短パスアルゴリズムを修正していましたが、ビデオでは、教師はBFS/DFSを直接見つけることはできないと述べています最短経路加重グラフ(私は誰もがこれをすでに知っていると思います)そして動作すると言いました自分で理由を突き止めてください。

重み付きグラフに使用できない正確な理由/説明を疑問に思っていました。それはエッジの重みか何かのためですか?少し混乱しているので、誰か説明してくれますか。

PS: this questionと this questionを試しました。

20
user2125722

このようなグラフを考えてみましょう:

A---(3)-----B
|           |
\-(1)-C--(1)/

AからBへの最短経路は、Cを経由します(総重量2)。通常のBFSは、AからBに直接パスを取り、Bをマークし、AからCにマークし、Cをマークします。

次の段階では、CからBへの伝搬は既に見られるようにマークされているため、CからBへのパスは潜在的な短いパスとは見なされず、BFSはAからBへの最短パスに重みがあることを通知します3。

BFSの代わりに Dijkstraのアルゴリズム を使用して、重み付きグラフの最短パスを見つけることができます。機能的には、アルゴリズムはBFSと非常によく似ており、BFSと同様の方法で記述できます。変更されるのは、ノードを考慮する順序だけです。

たとえば、上記のグラフでは、Aから開始して、BFSはA-> Bを処理し、次にA-> Cを処理し、すべてのノードが表示されているのでそこで停止します。

一方、ダイクストラのアルゴリズムは次のように動作します。

  1. A-> Cを考慮します(これはAからの最も低いエッジの重みであるため)
  2. C-> Bを考慮します(これは、これまでに到達したノードの中で最も重みが低いため、まだ考慮していません)
  3. Bはすでに見られているので、A-> Bを考慮して無視してください。

違いは、エッジが検査されるorderにあることに注意してください。 BFSは、他のノードに移動する前に、単一ノードからのallエッジを考慮しますが、ダイクストラのアルゴリズムは、常に最小の重量を考慮しますnseenこれまでに見られたすべてのノードに接続されたエッジのセットからのエッジ。紛らわしいように聞こえますが、擬似コードは非常に単純です。

create a heap or priority queue
place the starting node in the heap
dist[2...n] = {∞}
dist[1] = 0
while the heap contains items:
   vertex v = top of heap
   pop top of heap
   for each vertex u connected to v:
       if dist[u] > dist[v] + weight of v-->u:
           dist[u] = dist[v] + weight of Edge v-->u
           place u on the heap with weight dist[u]

ウィキペディアのこのGIFは、何が起こるのかを視覚的に示しています。

Dijkstra

これはBFSコードと非常によく似ていることに注意してください唯一の本当の違いは、通常のキューデータ構造ではなく、ノードまでの距離でソートされたヒープの使用です。

33
Greg

これは本当ですが、重み付きグラフでBFS/DFSを使用できます。グラフを少し変更すると、グラフの重みが正の整数である場合、Edgeを重みnで、nで、_1でn-1中間ノード。このようなもの:

A-(4)-B

なります:

A-(1)-M1-(1)-M2-(1)-M3-(1)-B

また、BFS/DFSの最終結果でこれらの中間ノード(M1、M2、M3など)を考慮しないでください。


このアルゴリズムの複雑さはO(V * M)であり、特定のグラフM<log Vでこのアルゴリズムを考慮することができることがわかっている場合、Mはエッジの最大重みですが、一般にこのアルゴリズムは良い成果。

3
Lrrr