Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Data Structures and Algorithms in C++ 2e (На ру...docx
Скачиваний:
0
Добавлен:
01.07.2025
Размер:
2.37 Mб
Скачать

13.4. Направленные графы 631

Суждение 13.18: Поскольку я = 1..., n, у диграфа GK есть край (vi, v j) если и только если

у диграфа G есть направленный путь от vi до v j, чьи промежуточные вершины (если таковые имеются)

в набореv1..., vk. В частности Gn равен G*, переходное закрытие G.

Суждение 13.18 предлагает простой алгоритм для вычисления переходного clo-верного из G, который основан на серии раундов, которые мы описали выше. Этот алгоритм известен как алгоритм Флойда-Вошола, и его псевдокодекс дан в Кодовом Фрагменте 13.22. Из этого псевдокодекса мы можем легко проанализировать продолжительность алгоритма Флойда-Вошола, предполагающего, что структура данных, представляющая G глоток - порты, функционирует isAdjacentTo и insertDirectedEdge в O (1) время. Главная петля выполнена, n времена и внутренняя петля считают каждый из O (n2) парами вершин, выполняя постоянно-разовое вычисление для каждого. Таким образом полная продолжительность алгоритма Флойда-Вошола - O (n3).

Алгоритм FloydWarshall (G):

Вход: диграф G с n Продукцией вершин: переходное закрытие G* G позволило v1, v2..., vn быть произвольной нумерацией вершин G

G0 К G

поскольку k¬ 1 к n делает

G k¬ G k-1

для всего я, j в1..., n\со мной = j и я, j = k делаю

если оба края (vi, vk) и (vk, v j) находятся в Gk 1 тогда

добавьте край (vi, v j) к GK (если это уже не присутствует),

возвратите Gn

Кодовый Фрагмент 13.22: псевдокодекс для алгоритма Флойда-Вошола. Этот algo-rithm вычисляет переходное закрытие G* G, с приращением вычисляя ряд диграфов G0, G1..., Gn, где k = 1..., n.

Это описание - фактически пример алгоритмического шаблона, известного как динамическое программирование, которое обсуждено более подробно в Разделе 12.2. Из описания и анализа выше, мы можем немедленно получить следующий propo-sition.

Суждение 13.19: Позвольте G быть диграфом с n вершинами и позволить G быть представленным структурой данных, которая поддерживает поиск и обновление информации о смежности в O (1) время. Тогда алгоритм Флойда-Вошола вычисляет переходное закрытие G*G в O (n3) время.

Мы иллюстрируем пробег в качестве примера алгоритма Флойда-Вошола в рисунке 13.10.

632 Глава 13. Алгоритмы графа

(a) (b)

(c) (d)

(e) (f)

Рисунок 13.10: Последовательность диграфов, вычисленных алгоритмом Флойда-Вошола: (a) первоначальный диграф G = G0 и нумерация вершин; (b) диграф G1; (c) G2; (d) G3; (e) G4; (f) G5. (Отметьте что G5 = G6 = G7.), Если у диграфа Gk 1 есть края (vi, vk) и (vk, v j), но не край (vi, v j). В рисунке диграфа GK мы показываем края (vi, vk) и (vk, v j) с расплющенными синими линиями и краем (vi, v j) с толстой синей линией.

13.4. Направленные графы 633

Исполнение алгоритма Флойда-Вошола

Продолжительность алгоритма Флойда-Вошола, могло бы казаться, была бы медленнее, чем выполнение DFS направленного графа от каждой из его вершин, но это зависит от представления графа. Если граф представлен, используя матрицу смежности, то, управляя методом DFS однажды на направленном графе G берет O (n2) время (мы исследуем причину этого в Упражнении R-13.9). Таким образом управление DFS n времена берет O (n3) время, которое является не лучше, чем единственное выполнение алгоритма Флойда-Вошола, но алгоритм Флойда-Вошола был бы намного более прост осуществить. Тем не менее, если граф представлен, используя структуру списка смежности, то управление алгоритмом DFS n времена взяло бы O (n (n + m)) время, чтобы вычислить переходное закрытие. Несмотря на это, если граф плотный, то есть, если у него естьW (n2) края, тогда этот подход все еще управляет в O (n3) временем и более сложен, чем единственный случай алгоритма Флойда-Вошола. Единственный случай, неоднократно называние метода DFS лучше, - когда граф не плотный и представлен, используя структуру списка смежности.

13.4.3 Направленные нециклические графы

С направленными графами без направленных циклов сталкиваются во многих заявлениях. Такой диграф часто упоминается как направленный нециклический граф или DAG, если коротко. Применения таких графов включают следующее:

• Наследование между классами C ++ программа

• Предпосылки между курсами программы на получение степени • Планирование ограничений между задачами проекта

Пример 13.20: Чтобы управлять крупным проектом, удобно разбить его

в коллекцию меньших задач. Задачи, однако, редко независимы, быть - ограничения планирования причины существуют между ними. (Например, в проекте строительства дома, задача заказа гвоздей, очевидно, предшествует задаче прибивания опоясывающего лишая к настилу крыши.) Ясно, у намечания ограничений не может быть округлостей, потому что они сделали бы проект невозможным. (Например, чтобы получить работу, у Вас должен быть опыт работы, но чтобы получить опыт работы, у Вас должна быть работа.) Ограничения планирования вводят ограничения для заказа, в котором могут быть выполнены задачи. А именно, если ограничение говорит, что задача, необходимость быть законченной перед задачей b начата, тогда необходимость предшествует b в заказе выполнения задач. Таким образом, если мы моделируем выполнимый набор задач как вершины направленного графа, и мы помещаем направленный край от v до w каждый раз, когда задача для v должна быть выполнена перед задачей для w тогда мы определяем направленный нециклический граф.

634