Статья Автор: Деникина Н.В., Деникин А.В.

Кратчайший путь в графе: через вершину и в обход

Если путь лежит через вершину X

Путь через X разрезается этой вершиной на два куска, и каждый выгодно делать кратчайшим отдельно.


кратчайший 1 → X кратчайший X → 100 1 X 100 d[X] по обычным рёбрам + d[X] по перевёрнутым рёбрам

В таблице Флойда оба куска уже посчитаны, так что ответ — это одна строка.

W[1][X] + W[X][100] и всё.

Форд–Беллман тут проиграет: пришлось бы запускать его дважды, причём второй раз по перевёрнутым рёбрам, чтобы получить расстояния до сотни.
 

Если путь лежит в обход вершины X

Вершину надо выкинуть из графа вместе со всеми её рёбрами — и входящими, и выходящими. В таблице это одна проверка при чтении файла: не заносим ребро, если оно касается X.

Если X не лежала на кратчайшем пути, ответ не изменится. Это нормально и часто бывает.


Пример

Посчитаем: обычный кратчайший путь, путь через вершину 486 и путь в обход вершины 670.


Одна строка вместо второго алгоритма

Когда таблица Флойда готова, путь через вершину складывается из двух её клеток. Посмотрим на числа.



Результат работы программы
40.900000000000006

Ограничение не может помочь: путь через заданную вершину всегда не короче обычного. А если хоть одна из двух клеток бесконечна, такого пути просто не существует.


Разбор программы
строка что делает
W[1][486] + W[486][100] путь через вершину — две клетки таблицы
if v1 != 670 and v2 != 670 ребро не заносится, если касается запрещённой вершины
B = [[INF] * 1001 ...] для запрета строим вторую таблицу с нуля
for k in vertices вторую таблицу тоже надо прогнать через Флойда


Что печатает программа
30.799999999999997
40.9
78.0

Через 486 путь длиннее обычного — так и должно быть: лишнее требование не может помочь.

Запрет вершины 670 стоит дороже всего: она лежала на кратчайшем пути, и без неё остаётся единственная дорога 1 → 810 → 100.


Ловушки

  • Написали W[1][X] + W[100][X]. Второй кусок идёт из X в сотню, а не наоборот.
  • Запретили вершину, но выбросили только выходящие из неё рёбра.
  • Посчитали обычный кратчайший путь и обрадовались, что он и так проходит через X. Проверять надо, а не надеяться.
  • Сложили две бесконечности и напечатали inf. Значит, такого пути через X просто нет.

Проверь себя


Файл graph.txt: сопоставьте вершину и длину кратчайшего пути из 1 в 100 через неё.

Файл graph.txt: целая часть длины кратчайшего пути из 1 в 100, не проходящего через вершину 810.
Attached files
graph.txt
Печать