Я провел небольшое исследование, и мне кажется, что мне не хватает одной маленькой части этого алгоритма. Я понимаю, как работает поиск в ширину, но не понимаю, как именно он приведет меня к конкретному пути, а не просто скажет мне, куда может пойти каждый отдельный узел. Думаю, самый простой способ объяснить мое замешательство - это привести пример:
Так, например, у меня есть такой график:
И моя цель - добраться от A до E (все ребра не взвешены).
Я начинаю с А, потому что это мое происхождение. Я ставлю A в очередь, после чего немедленно удаляю A из очереди и исследую его. Это дает B и D, потому что A соединен с B и D. Таким образом, я ставлю в очередь B и D.
Я удаляю B из очереди и исследую его, и обнаруживаю, что он ведет к A (уже исследованному) и C, поэтому я ставлю в очередь C. Затем я удаляю D из очереди и обнаруживаю, что он ведет к E, моей цели. Затем я удаляю C из очереди и обнаруживаю, что это также приводит к E, моей цели.
Я логически знаю, что самый быстрый путь - A-> D-> E, но я не уверен, как именно помогает поиск в ширину - как мне записывать пути, чтобы, когда я закончу, я могу проанализировать результаты и увидеть что кратчайший путь A-> D-> E?
Также обратите внимание, что я на самом деле не использую дерево, поэтому нет «родительских» узлов, только дочерние элементы.
Ответы:
Технически, поиск в ширину (BFS) сам по себе не позволяет вам найти кратчайший путь просто потому, что BFS не ищет кратчайший путь: BFS описывает стратегию поиска графа, но не говорит, что вы должны искать что-нибудь конкретное.
Алгоритм Дейкстры адаптирует BFS, чтобы вы могли находить кратчайшие пути из одного источника.
Чтобы получить кратчайший путь от источника к узлу, вам необходимо поддерживать два элемента для каждого узла в графе: его текущее кратчайшее расстояние и предыдущий узел кратчайшего пути. Изначально все расстояния установлены на бесконечность, а все предшественники установлены на пустые. В вашем примере вы устанавливаете расстояние A равным нулю, а затем продолжаете работу с BFS. На каждом шаге вы проверяете, можете ли вы улучшить расстояние до потомка, то есть расстояние от начала координат до предшественника плюс длина края, который вы исследуете, меньше текущего лучшего расстояния для рассматриваемого узла. Если вы можете увеличить расстояние, установите новый кратчайший путь и запомните предшественника, через который этот путь был получен. Когда очередь BFS пуста, выберите узел (в вашем примере это E) и переместите его предшественников обратно в источник.
Если это звучит немного запутанно, в Википедии есть хороший раздел псевдокода по этой теме.
источник
Как было отмечено выше, BFS может только быть использована , чтобы найти кратчайший путь в графе , если:
Петель нет
Все ребра имеют одинаковый вес или не имеют веса.
Чтобы найти кратчайший путь, все, что вам нужно сделать, это начать с источника и выполнить поиск в ширину, а затем остановиться, когда вы найдете целевой узел. Единственное, что вам нужно сделать, это иметь массив previous [n], который будет хранить предыдущий узел для каждого посещенного узла. Предыдущее значение источника может быть нулевым.
Чтобы распечатать путь, просто переберите массив previous [] от источника до места назначения и распечатайте узлы. DFS также может использоваться для поиска кратчайшего пути в графе в аналогичных условиях.
Однако, если граф более сложный, содержащий взвешенные ребра и петли, тогда нам понадобится более сложная версия BFS, то есть алгоритм Дейкстры.
источник
To print the path, simple loop through the previous[] array from source till you reach destination.
Но предыдущее значение источника равно нулю. Я думаю , что вы имели в виду это,backtrace from destination using the previous array until you reach the source
.Из учебника здесь
источник
Я потратил 3 дня, в
конечном итоге решил вопрос с графиком,
используемый для
поиска кратчайшего расстояния
с помощью BFS.
Хочу поделиться опытом.
Я потерял 3 дня, пробуя все вышеперечисленные альтернативы, проверяя и повторно проверяя снова и снова, выше
они не являются проблемой.
(Попробуйте потратить время на поиск других проблем, если вы не нашли проблем с выше 5).
Дополнительное объяснение из комментария ниже:
Предположим, что выше ваш граф-
график идет вниз.
Для A, смежные - B и C.
Для B, смежные - D и E.
Для C, смежные - F и G.
скажем, начальным узлом является A
когда вы достигнете A, до, B и C, кратчайшее расстояние до B и C от A равно 1
когда вы достигнете D или E, через B, кратчайшее расстояние до A и D равно 2 (A-> B-> D)
аналогично, A-> E равно 2 (A-> B-> E)
кроме того, A-> F & A-> G равно 2
Итак, теперь вместо 1 расстояния между узлами, если оно равно 6, просто умножьте ответ на 6
примеров,
если расстояние между каждым из них равно 1, тогда A-> E равно 2 (A-> B-> E = 1 + 1 )
если расстояние между ними равно 6, то A-> E равно 12 (A-> B-> E = 6 + 6)
да, бойцы могут пойти по любому пути
но мы рассчитываем для всех путей
если вам нужно пройти от A до Z, тогда мы проходим все пути от A до промежуточного I, и, поскольку будет много путей, мы отбрасываем все, кроме кратчайшего пути до I, а затем продолжаем кратчайший путь до следующего узла J
снова, если есть несколько путей от I до J, мы берем только один самый короткий
пример,
предположим,
A -> I у нас есть расстояние 5
(ШАГ) предположим, I -> J у нас есть несколько путей с расстояниями 7 и 8, поскольку 7 является самым коротким
мы берем A -> J как 5 (A-> I самое короткое) + 8 (самое короткое сейчас) = 13,
так что A-> J теперь 13,
мы повторяем теперь выше (STEP) для J -> K и так далее, пока не получим к Z
Прочтите эту часть 2 или 3 раза и нарисуйте на бумаге, вы обязательно поймете, о чем я говорю, удачи
источник
На основе acheron55 ответ я отправил возможную реализацию здесь .
Вот его краткое изложение:
Все, что вам нужно сделать, это отслеживать путь, по которому была достигнута цель. Простой способ сделать это - протолкнуть
Queue
весь путь, используемый для достижения узла, а не сам узел.Преимущество этого заключается в том, что, когда цель достигнута, очередь содержит путь, используемый для ее достижения.
Это также применимо к циклическим графам, где у узла может быть более одного родителя.
источник
Посещение этой ветки после некоторого периода бездействия, но с учетом того, что я не вижу подробного ответа, вот мои два цента.
Поиск в ширину всегда находит кратчайший путь в невзвешенном графе. График может быть циклическим или ациклическим.
См. Псевдокод ниже. Этот псевдокод предполагает, что вы используете очередь для реализации BFS. Также предполагается, что вы можете пометить вершины как посещенные, и что каждая вершина хранит параметр расстояния, который инициализируется как бесконечность.
Обратите внимание, что этот подход не работает для взвешенных графов - для этого см. Алгоритм Дейкстры.
источник
Следующее решение работает для всех тестовых случаев.
источник