Алгоритм Бхандари - sergeresko/Lem_in-explanation GitHub Wiki

Помню, из статьи не всё было ясно и кое о чём приходилось догадываться. Вот шаги алгоритма Бхандари для лучшего понимания:

Граф имеет исходный вид (все рёбра двунаправленные с весом 1). Если это первый запуск алгоритма, то все pred/succ равны NULL; если не первый — некоторые из них не NULL и описывают уже найденные пути. У комнат start и end они всегда NULL.

1) modify graph

для каждого пути, обозначенного с помощью pred/succ, произвести раздвоение вершин (включая действия, касающиеся рёбер)

2) find path

выполнить алгоритм Дейкстры (перед его запуском надо, чтоб у всех комнат, в т.ч. созданных в результате раздвоения, значения полей были сброшены к distance = ∞ и parent = NULL)

Если алгоритму Дейкстры удалось найти путь, то он состоит из комнат, в которые можно попасть, переходя по полю parent, начиная с комнаты end. Если ему не удалось найти путь, то parent комнаты end равен NULL.

3) adjust parents

подготовить граф к слиянию вершин (нужно некоторым комнатам поменять значения parent, чтобы при последующем удалении комнат, которые образовались при раздвоении, цепочка parent не нарушилась)

Например, допустим, что некоторая вершина X исходного графа была раздвоена: из неё получились X' и X". Может оказаться, что путь, описываемый полями parent, проходит через X' либо через X" либо через обе X' и X". Нужно добиться того, чтобы в любом из этих случаев после объединения этих вершин обратно в X путь проходил через X.

4) restore graph

для каждого пути, обозначенного в графе с помощью pred/succ, произвести слияние вершин (включая действия, касающиеся рёбер)

В результате граф станет идентичным исходному, за исключением значений distance и parent.

5) combine paths

обновить значения pred/succ в соответствии с правилом наложения путей

Т.е. мы проходим по пути, ведущему от end к start через поля parent, и, если какое-то его ребро ещё не обозначено в pred/succ, обозначаем его; иначе (если оно уже обозначено), «удаляем» его, устанавливая соответствующие pred/succ в NULL. В итоге pred/succ будут описывать новый набор путей.


Дальше: Иллюстрация