Алгоритм Косараджу По Полочкам

Ээта статья продолжается обсуждение как более понятно объяснить алгоритм Косараджу — поиск сильно связных компонент в графе.

В статье дано изложение и обоснование корректности алгоритма.

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

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



Базовые концепты



Алгоритм Косараджу по полочкам

сильно связные вершины u, v Пики ты, в называются сильно связан , если в графе G существует путь (не обязательно прямой) и→в И в→у (Обозначим сильно связные вершины и↔в ), и для каждой вершины ты истинный ты ты

Алгоритм Косараджу по полочкам

Компоненты сильной связи Компоненты сильной связи -- максимальные сильно связные подграфы Инвертировать граф -- изменение направления всех ребер в графе на противоположное (двунаправленное ребро остаётся самим собой) часы DFS от верхней в -- обойти ( в глубине ) все вершины графа, достижимые из в .

Тик можно интерпретировать как рекурсивный вызов функции.

Цикл обработки вершины, не имеющей соседей, будет равен 1. Максимальное время выхода -- число, соответствующее времени выхода рекурсии алгоритма DFS из вершины.

Более того, изначально счетчик времени равен 0; оно увеличивается только в двух случаях:

  1. Начало нового тика DFS
  2. Прохождение по ребру (неважно, рекурсивный это проход или нет)
Пример назначения времени выхода: Учитывая следующий график:

Алгоритм Косараджу по полочкам

Обойдем его с помощью алгоритма DFS, разметив вершины по правилам, указанным выше:

Алгоритм Косараджу по полочкам

Мы обозначаем непройденные вершины знаком '?' Мы выберем начальную вершину в порядке возрастания непомеченных вершин.

Изначально счетчик 0

Алгоритм Косараджу по полочкам

Начинаем новый цикл с выбора вершины 0 (как вершины с минимальным индексом).

Увеличиваем счетчик на 1 и присваиваем это число метке вершины 0. Попутно мы построим деревья часов DFS справа от исходного графа.



Алгоритм Косараджу по полочкам

У вершины 0 только один сосед — вершина 2. Идем по ребру 0-2, увеличивая счетчик и присваивая метку вершине 2.

Алгоритм Косараджу по полочкам

У узла 2 нет соседей.

Поэтому все, что мы можем сделать, это рекурсивно вернуться к предыдущей вершине (чтобы понять, какая вершина была предыдущей, мы строим дерево).

Идя по рекурсивному ребру 2-0, мы увеличиваем счетчик на 1 и присваиваем вершине 0 новую метку.



Алгоритм Косараджу по полочкам

У вершины 0 больше нет непомеченных соседей — цикл завершается.

Начиная новый цикл, мы увеличиваем счетчик и присваиваем метку счетчика следующей (по возрастанию) вершине.

Также начинаем строить дерево нового такта.



Алгоритм Косараджу по полочкам

У вершины 1 есть 2 соседа: 0 и 3. Но у вершины 0 уже есть метка — перейти к ней нельзя.

Затем идем в вершину 3, увеличивая счетчик и присваивая метку

Алгоритм Косараджу по полочкам

У вершины 5 нет непомеченных соседей.

Возвращаемся к предыдущей вершине, увеличивая счетчик и присваивая новую метку

Алгоритм Косараджу по полочкам

У вершины 1 больше нет соседей — цикл завершается.

Мы также видим, что все вершины отмечены.

Алгоритм поиска в глубину завершен Из примера видно, что вершина в начале такта (корень) имеет самую большую (в такте) метку - это объясняется рекурсивностью алгоритма DFS - алгоритм заходит в одну вершину и оставляет то же самое.

Этот факт понадобится в доказательстве.

Вот несколько простых лемм: Лемма 1 : Если правда ты в И в ш , тогда правда и↔в Доказательство : Поскольку и↔в , Что в достижим из ты , у нас также есть v↔w , Означает ш достижим из в .

Следовательно ш достижим из ты , сходным образом, ты достижим из ш .

Мы получаем и↔в Лемма 2 : Сильно связная компонента — это множество вершин, входящих в множество циклы, имеющие хотя бы одну общую вершину

Алгоритм Косараджу по полочкам

цикл A имеет общую вершину u с циклом B Доказательство : Заметим, что все вершины одного цикла входят в одну компоненту связности, так как по циклу из любой его вершины можно дойти до другой.

Если два цикла имеют общую точку, то через нее можно перейти к вершинам другого цикла и достичь любой из них.

Таким образом, все вершины, принадлежащие связным циклы между собой, включены в одну связную компоненту.

Рассмотрим любое из максимальных объединений циклов С .

Докажем, что вершина не включен в С , принадлежит другой сильно связной компоненте.

Докажем это от противного.

Пусть вершина v не входит в объединение циклов С , но сильно связан с одной из вершин этих циклы ты .

Тогда по определению сильной связи существует путь из вершины в до ты и путь от пики ты до в .

Склеив (конкатенацией) эти пути, мы получим цикл, связанный с объединением циклически проходит через вершину ты , но не входит в С , что противоречит предположению.

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

Лемма 3 : Инвертирование ребер цикла не влияет на его цикличность.

Доказательство : Если исходный граф имеет путь от ты В в , то инвертированный граф будет иметь путь из в В ты.



Алгоритм Косараджу

Алгоритм Косараджу предназначен для поиска сильно связанных компонентов в ориентированном графе и состоит из трех шагов:
  1. Выполняйте поиск в глубину (DFS), пока все вершины не будут «помечены».

    Вершина считается «помеченной», когда ей назначается время выхода из рекурсии (см.

    основные понятия).

  2. Инвертировать исходный график
  3. Выполните DFS в порядке убывания меток вершин.

Результирующие деревья каждого такта DFS последнего шага представляют собой сильно связные компоненты.

Прежде чем доказывать алгоритм, предлагаю посмотреть на примере, как работает алгоритм.



Пример пошаговой работы алгоритма Косараджу

Учитывая следующий график:

Алгоритм Косараджу по полочкам



Алгоритм Косараджу по полочкам

Шаг 1: Непомеченные вершины помечены знаком '?' Справа от исходного графика находится лес DFS. Начальная вершина выбирается в порядке возрастания индексов.

Полный протокол работы я не показывал, но он доступен в разделе «основные понятия».



Алгоритм Косараджу по полочкам

Шаг 2: Инвертирование краев

Алгоритм Косараджу по полочкам

Шаг 3: Выбираем начальную вершину в порядке убывания меток.

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

Справа от перевернутого графика показывает лес часов DFS

Алгоритм Косараджу по полочкам

После завершения алгоритма у нас есть 3 сильно связных компонента.



Доказательство корректности алгоритма

Давайте немного уточним, что нужно доказать : Пики ты И в сильно связанный после выполнения алгоритма они принадлежат одному и тому же дереву часов DFS. Доказательство : Если вершины ты И в были сильно связны в графе G, то на третьем этапе будет найден путь от одной вершины к другой (по лемме 3), так как на первом шаге путь и → в, и на третьем - путь в→у.

Это означает, что в конце алгоритма обе вершины лежат в одном дереве.



Алгоритм Косараджу по полочкам

Пики ты И в лежат в одном и том же дереве поиска в глубину на третьем шаге алгоритма.

Это означает, что они оба доступны из корня р это дерево.

Вертекс р рассматривалась на шаге 3 раньше всех остальных, а значит время выхода из него на шаге 1 больше, чем время выхода из вершин ты И в .

Отсюда получаем 2 случая:

  1. Обе эти вершины были достижимы из р в исходном графике.

    Это означает сильную связность вершин ты И р и сильная связность вершин в И р (согласно лемме 3).

    Склеивая пути получаем связность вершин ты И в (по лемме 1)

  2. По крайней мере одна вершина не достижима из р в исходном графике, например в .

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

    Это означает, что пути между этими вершинами нет (ни в исходном, ни в инвертированном графе), а последний существовать не может, поскольку по условию в достижим из р на шаге 3 (в перевернутом графике)

Это означает, что из случая 1 и отсутствия случая 2 получаем, что вершины ты И в сильно связны в обоих графах

Сложность алгоритма

Поиск в глубину в исходном графе выполняется за O(V+E) Чтобы инвертировать все ребра в графе, представленном в виде списка смежности, требуются действия O(V+E).

Для матричного представления графика не требуется предпринимать никаких действий для его инвертирования (индексы столбцов будут использоваться в качестве индексов строк и наоборот) Количество ребер в инвертированном графе равно количеству ребер в исходном графе, поэтому поиск в глубину будет выполняться за O(V+E).

В результате получаем, что при нижней оценке Сложность алгоритма - O(V+E) Верхняя оценка (когда у нас полный граф) будет следующей (напомним, что количество ребер в полном графе равно н вершины равны п(п-1)/2 ):

Алгоритм Косараджу по полочкам

То есть в худшем случае мы имеем квадратичная сложность

Нижняя граница

Алгоритм Косараджу ищет сильно связанные компоненты, и делает это за время в лучшем случае O(V+E), а в худшем — за O(V^2).

Где применить алгоритм, полностью зависит от вашей фантазии по созданию графиков.

Например: проецирование транспортной сети на граф.

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

Вы можете использовать алгоритм для проверки системы воздуховодов в зданиях; ток в полупроводниковых устройствах Можно мыслить шире: мы проектируем кровеносную систему живого существа, которую вам поручили создать в рамках проекта генной инженерии, где-то в 2077 году).

Алгоритм поможет узнать, доходит ли кровь до органов и обратно от сердца.

Теги: #Алгоритмы #Косарайю #сильно связанные компоненты

Вместе с данным постом часто просматривают:

Автор Статьи


Зарегистрирован: 2019-12-10 15:07:06
Баллов опыта: 0
Всего постов на сайте: 0
Всего комментарий на сайте: 0
Dima Manisha

Dima Manisha

Эксперт Wmlog. Профессиональный веб-мастер, SEO-специалист, дизайнер, маркетолог и интернет-предприниматель.