Использование BFS для взвешенных графов

я пересматривал алгоритмы кратчайшего пути с одним источником, и в видео учитель упоминает, что BFS / DFS не может использоваться непосредственно для поиска кратчайших путей на взвешенного графа (Я думаю, все это уже знают) и сказал, чтобы выяснить причину самостоятельно.

Мне было интересно узнать точную причину / объяснение, почему его нельзя использовать для взвешенных графиков. Это из-за веса ребер или что-то еще ? Может кто-нибудь объясните мне, как я чувствую себя немного запутался.

PS: я прошел этой сомнение и этой вопрос.

2 ответов


рассмотрим такой график:

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 найти кратчайший путь на взвешенном графике. Функционально алгоритм очень похож на BFS и может быть написан аналогично BFS. Единственное, что меняется-это порядок, в котором вы считаете узлов.

например, на приведенном выше графике, начиная с A, BFS будет обрабатывать A --> B, затем A --> C и останавливаться там, потому что все узлы были замечены.

С другой стороны, алгоритм Дейкстры будет действуйте следующим образом:

  1. рассмотрим A --> C (так как это самый низкий вес края от A)
  2. рассмотрим C --> B (так как это край с наименьшим весом из любого узла, которого мы достигли до сих пор, что мы еще не рассматривали)
  3. рассмотреть и игнорировать A --> B, так как B уже был замечен.

обратите внимание, что разница заключается просто в ордер в котором края проверены. A BFS рассмотрит все ребра от одного узла перед переходом к другим узлам, в то время как алгоритм Дейкстры всегда будет учитывать самый низкий-вес невидимый edge, из набора ребер, подключенных к все узлы, которые наблюдались до сих пор. Это звучит запутанно, но псевдокод очень прост:

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/DFS в взвешенных графах с небольшим изменением графика, Если веса вашего графика являются целыми положительными числами, вы можете заменить ребро на вес n С n края с весом 1 с n-1 средние узлы. Что-то вроде этого:--8-->

A-(4)-B

будет:

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

и не учитывайте эти средние узлы (например,M1,M2, M3 ) в ваших конечных результатах BFS/DFS.


эта сложность алгоритма равна O (V * M) и M-максимальный вес наших ребер, если мы знаем, что в наших конкретных графах M<log V этот алгоритм может быть рассмотрен, но в целом этот алгоритм может не иметь такой хорошей производительности.