Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Высокоцровневые методы информатики и првые методы информатики и программированияограммирования.doc
Скачиваний:
332
Добавлен:
01.05.2014
Размер:
14.7 Mб
Скачать

5.3.2 Сильно связные компоненты

Классическое применение поиска в глубину задача о разложении графа на сильно связные компоненты. Мы покажем, как это можно сделать, дважды выполнив поиск в глубину.

Многие алгоритмы, работающие на ориентированных графах, начинают с отыскания сильно связных компонент: после этого задача решается отдельно для каждой компоненты, а потом решения комбинируются в соответствии со связями между компонентами. Эти связи можно представлять в виде так называемого «графа компонент».

Алгоритм поиска сильно связных компонент графа G = (VЕ) будет ис- пользовать «транспонированный» граф GT = (VЕT), получаемый из исходного обращением стрелок на рёбрах: ЕT = ((u, v): (v, и) E). Такой граф можно построить за время O(V Е) (мы считаем, что исходный и транспони- рованный графы заданы с помощью списков смежных вершин). Легко понять, что G и GT имеют одни и те же сильно связные компоненты (поскольку v до- стижимо из и в GT, если и только если и достижимо из v в GT). На рисунке 5.5(б) показан результат транспонирования графа рис. 5.5(а).

Рисунок 5.5 – Выделение сильно связных компонент

(а) Ориентированный граф G и его сильно связные компоненты (показаны серым). Показан лес поиска в глубину и метки времени для графа G. (б) Транс- понированный граф G. Показан лес поиска в глубину, вычисляемый в строке 3 процедуры STRONGLY-CONNECTED-COMPONENTS. Рёбра дерева обведены серым. Вершины bсgh, являю- щиеся корнями деревьев поиска в глубину (для графа G), выделены чёрным. (в) Ацикличе- ский граф, который получится, если стянуть каждую сильно связную компоненту графа G в точку.

Следующий алгоритм находит сильно связные компоненты ориентированно- го графа G = (VЕ), используя два поиска в глубину – для G и для GT; время работы есть O(V + Е).

Листинг 5.7 – Алгоритм поиска сильно связных компонент

5.4 Алгоритм построения минимального остовного дерева

5.4.1 Остовные деревья минимальной стоимости

Пусть даны n контактов на печатной плате, которые мы хотим электрически со- единить. Для этого достаточно использовать n 1 проводов, каждый из которых соединяет два контакта. При этом мы обычно стремимся сделать суммарную длину проводов как можно меньше.

Упрощая ситуацию, можно сформулировать задачу так. Пусть имеется связ- ный неориентированный граф G = (VЕ), в котором V  множество контактов, а Е множество их возможных попарных соединений. Для каждого ребра гра- фа (и, v) задан неотрицательный вес w(и, v) (длина провода, необходимого для соединения и и v). Задача состоит в нахождении подмножества Т Е, связы- вающего все вершины, для которого суммарный вес

минимален. Такое подмножество Т можно считать деревом (в любом цикле один из проводов можно удалить, не нарушая связности). Связный подграф графа G, являющийся деревом и содержащий все его вершины, называют покрывающим деревом (spanning tree) этого графа. (Иногда используют термин «остовное дерево», или, короче, «остов».)

В этом разделе мы рассматриваем задачу о минимальном покрывающем дереве (minimum-spanning-tree problem). Здесь слово «минимальное» означает «имеющее минимально возможный вес». (Заметим в скобках, что если мы рассматриваем только деревья, то условие неотрицательности весов можно отбросить, посколь- ку во всех покрывающих деревьях одинаковое число рёбер и все веса можно изменить на одну и ту же константу, сделав их положительными.) На рисунке 5.6 приведён пример связного графа и его минимального остова.

Возвращаясь к примеру с проводниками на печатной плате, объясним, по- чему задача о минимальном дереве является упрощением реальной ситуации. В самом деле, если соединяемые контакты находятся в вершинах единичного квадрата, разрешается соединять его любые вершины и вес соединения равен его длине, то минимальное покрывающее дерево будет состоять из трёх сторон квадрата. Между тем все его четыре вершины можно электрически соединить двумя пересекающимися диагоналями (суммарная длина < 3) и это ещё не предел (можно ввести две промежуточные точки, в которых проводники сходятся под углом 1200).

В этом разделе мы рассмотрим два способа решения задачи о минимальном покрывающем дереве: алгоритмы Крускала и Прима. Каждый их них легко реализовать с временем работы O(Е  log V), используя обычные двоичные ку- чи. Применив фибоначчиевы кучи, можно сократить время работы алгоритма Прима до O(+ V  log V) (выигрыш существен, если |V| много меньше |Е|).

Оба алгоритма (Крускала и Прима) следуют «жадной» стратегии: на каждом шаге выбирается «локально наилучший» вариант. Не для всех задач такой выбор приведёт к оптимальному решению, но для задачи о покрывающем дереве это так.

Рисунок 5.6 – Связный граф и его минимальный остов

На рис. 5.6 изображено минимальное покрывающее дерево. На каждом ребре графа указан вес. Выделены рёбра минимального покрывающего дерева (суммарный вес 37). Такое дерево не единственно: заменяя ребро (bc) ребром (аh), получаем другое дерево того же веса 37.