- •Лекция 1. Введение
- •Лекция 2. Графы и деревья
- •Лекция 3. Машинное представление графов
- •Лекция 4. Поиск в глубину в графе
- •Лекция 5. Поиск в ширину в графе
- •Лекция 6. Стягивающие деревья (кАркасы)
- •Лекция 7. Фундаментальное множество циклов графа
- •Лекция 8. Нахождение компонент двуcвязности (блоков) графа
- •Лекция 9. Эйлеровы пути
- •Лекция 10. Классификация задач по степени сложности
- •Лекция 11. Алгоритмы с возвратом
- •Лекция 12. Модификации алгоритма с возвратом. Задачи на максимум и минимум
- •Лекция 13. Кратчайшие пути
- •Лекция 14. Алгоритм форда-беллмана
- •Лекция 15. Алгоритм дейкстры
- •Лекция 16. Пути в бесконтурном графе
- •Лекция 17. Алгоритм флойда
- •Лекция 18. Кратчайшие пути с фиксированными платежами
- •Лекция 19. Первые k кратчайших путей
- •Приложение 1. Список np-полных задач
- •9. Множество представителей
- •10. Упорядочение внутри интервалов
- •11. Составление учебного расписания
- •Библиографический список
Лекция 17. Алгоритм флойда
Для решения задачи о кратчайших расстояниях между всеми парами вершин можно воспользоваться алгоритмом Форда-Беллмана, применив его n раз к каждой из вершин. Однако существует более эффективный алгоритм, который решает ту же задачу за О(n3) шагов.
Идея алгоритма следующая: будем искать кратчайшие расстояния D[i,j], постепенно увеличивая количество промежуточных вершин в пути от i до j. За начальные приближения возьмем пути от i до j без промежуточных вершин, т.е. веса ребер A[i,j].
Пусть уже известны длины D[i,j] самых коротких путей между всеми парами вершин, имеющих промежуточные вершины из множества 1..k-1. Добавим теперь к множеству промежуточных вершин вершину k. Путь от i до j будет складываться из пути от i до k и пути от k до j (см. рисунок 34).
Рис. 34
Так как наши пути не могут содержать повторяющихся вершин (иначе бы они не были кратчайшими), то пути от i до k и от k до j среди промежуточных вершин могут иметь только вершины из множества 1..k-1. Длины таких путей нам известны по предположению, поэтому длина пути от i до j, проходящего через k, сложится как сумма D[i,k]+D[k,j]. Остается сравнить старое значение D[i,j] с этой суммой и в качестве окончательного значения выбрать минимальное. Алгоритм заканчивает работу, когда промежуточными вершинами могут быть все вершины графа.
Алгоритм 6. {Флойд}
Данные: Орграф G=<V,E>, матрица весов A[u,v], u,vV.
Результаты: Расстояния D[i,j] между всеми парами вершин i,j V.
1 begin
2 for i:=1 to n do
3 for j:=1 to n do D[i,j]:=A[i,j];
4 for i:=1 to n do D[i,i]:=0;
5 for k:=1 to n do
6 for i:=1 to n do
7 for j:=1 to n do
8 D[i,j]:= min( D[i,j], D[i,k] + D[k,j] );
9 end.
Очевидно, что тройной цикл дает вычислительную сложность О(n3).
?Вопрос 5. Измените алгоритм печати пути исходя из того, что имеется двумерный массив расстояний D[i,j].
Ответы
Ответ 1. Цикл (6-7) находит ровно одну предыдущую вершину, но для печати всех путей нужно находить все такие вершины.
Ответ 2. Можно только в том случае, если при этом не образуется контур отрицательного веса.
Ответ 3. Да, всегда.
Ответ 4. Изменить веса дуг на противоположные. Граф бесконтурный, поэтому контуры отрицательного веса в нем не появятся.
Ответ 5. Чтобы найти путь от s до t в процедуру печати пути вместо одномерного массива D расстояний нужно передавть s–ю строку двумерного массива D.
Лекция 18. Кратчайшие пути с фиксированными платежами
Налево пойдешь — координат не соберешь, направо пойдешь — в бесконечность уйдешь, прямо пойдешь — транспонируешься. (Надпись на камне)
Все задачи о нахождении кратчайшего пути между двумя фиксированными вершинами исходили из следующего предположения: если кратчайший путь от s до t проходит через вершину k, то его отрезок от s до k будет кратчайшим путем от s до k и отрезок от k до t будет кратчайшим путем от k до t. Существует класс задач, для которых это не так. Это задачи с фиксированными платежами. Подобные задачи возникают в том случае, если за прохождение вершины сети взимается плата. Решаются такие задачи довольно сложно, но есть один класс транспортных задач, которые сводятся к уже рассмотренным нами задачам.
ШТРАФЫ ЗА ПОВОРОТЫ
Имеется сеть улиц с односторонним или двусторонним движением. Рассмотрим вначале случай одностороннего движения. При выполнении поворота вводится некая фиксированная плата — задержка или штраф.
Этот штраф зависит от направления движения при въезде и выезде. За выполнение запрещенного поворота взимается бесконечно большой штраф.
Рис. 35
Неотрицательные числа, приписанные дугам, представляют плату или время проезда. Кроме того, предполагается, что за выполнение каждого поворота взимается штраф, равный 3.
Требуется определить минимальный путь из 1 в 8.
Теорема
В сети со штрафами за повороты кратчайший путь из s в t, проходящий через k, не обязан содержать кратчайшие пути от s до k и от k до t.
Пример. (рис. 35)
1-2-3-4-8 — кратчайший путь со стоимостью 15.
1-2-3-4 — путь со стоимостью 11.
1-2-6-5-4 — кратчайший путь со стоимостью 10.
Мы уже умеем находить кратчайшие пути в задачах, где стоимости приписаны только дугам. Следовательно, по исходной сети нужно построить новую фиктивную сеть, где бы штрафы за повороты включились бы в стоимость дуг. Затем в фиктивной сети найти кратчайший путь и по нему восстановить кратчайший путь в исходной сети.
АЛГОРИТМ ПОИСКА КРАТЧАЙШЕГО ПУТИ В СЕТИ СО ШТРАФАМИ ЗА ПОВОРОТЫ
Шаг 1.
Ввести фиктивный источник s0 и соединить его дугой с источником s.
Ввести фиктивный сток t0 и соединить его дугой со стоком t.
Стоимости фиктивных дуг положить равными 0 и считать, что повороты из фиктивных вершин никогда не выполняются.
Шаг 2.
Каждой i-й дуге расширенной сети, полученной на шаге 1, приписать имя Li. Если исходная сеть содержала m дуг, то дугам будут приписаны имена L0,L1,…,Lm+1 (рис. 36).
Рис. 36
Шаг 3.
Построение фиктивной сети (рис. 37).
Каждой дуге расширенной сети будет соответствовать вершина фиктивной. Две вершины фиктивной сети Li и Lj соединены дугой только в том случае, если в исходной сети конец дуги Li был бы началом дуги Lj. Стоимость такой дуги определяется по следующей формуле: A(Li)+P(Li,Lj), где A(Li) — стоимость дуги Li, P(Li,Lj) — штраф за выполнение поворота.
Рис. 37
Стоимости дуг фиктивной сети:
L0–L1 |
L1–L2 |
L1–L8 |
L8–L7 |
L2–L3 |
L3–L9 |
L9–L6 |
L3–L4 |
L4–L5 |
L5–L10 |
L6–L10 |
L7–L6 |
0 |
1 |
4 |
5 |
3 |
4 |
5 |
1 |
9 |
3 |
4 |
2 |
?Вопрос 1. Почему стоимость дуги L5→L10 равна 3, а не 6 (стоимость дуги + штраф за поворот)?
Шаг 4.
Используя алгоритм Дейкстры, определить в фиктивной сети кратчайший путь.
Шаг 5.
По кратчайшему пути в фиктивной сети восстановить путь в исходной: вершина фиктивной сети→дуга исходной→начало дуги.
Останов.
Возникает вопрос, каким образом, зная две дуги, определить плату за поворот. В нашей задаче улицы имеют только два направления: горизонтальное и вертикальное. Будем хранить информацию о направлении каждой дуги в двумерном массиве BIN. Если BIN[i,j]=0, то дуга i→j имеет горизонтальное направление, если 1, то вертикальное.
Рассмотрим сумму BIN[i,j]+BIN[j,k], производя сложение по mod 2.
Если поворот происходит, то эта сумма равна 0+1 или 1+0, т.е. 1. Если поворот не происходит, то эта сумма равна 0+0 или 1+1, т.е. 0.
?Вопрос 2. Как хранить информацию о поворотах в случае двустороннего движения?
Подсчитаем вычислительную сложность алгоритма.
Построение фиктивной сети можно выполнить за O(n2) шагов. Если соответствие дуг исходной сети вершинам фиктивной записать в специальный массив размерности 2x(m+2), то восстановление пути пропорционально его длине, т.е. O(n). Алгоритм Дейкстры — O(n2). Окончательно, вычислительная сложность равна O(n2).
Ответы
Ответ 1. В фиктивную вершину поворот не производится.
Ответ 2. Кодировать возможные направления числами: 0,1,2,3.
