Зарегистрируйтесь для доступа к 15+ бесплатным курсам по программированию с тренажером

Взвешенный граф Теория графов

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

Что такое взвешенный граф

Взвешенный граф — это граф, в котором каждое ребро обозначается числом. Это число — его вес:

eyJpZCI6Ijg4NjZhN2RhMzg2MjEwNDExMGYxNDcyNzE4MmRiMjA1LnBuZyIsInN0b3JhZ2UiOiJjYWNoZSJ9?signature=5b2b1227c7bd42c727e17be0a920852f4ad457f082345418dfa62cf10c07bbc9

Вес — это стоимость использования данного ребра. Например, приведенный выше граф может представлять дорожную сеть, где вершины — это города, ребра — дороги между ними, а вес — стоимость строительства этих дорог.

Предположим, что мы хотим построить дороги, чтобы добраться из одного города в другой. Нам нужно сделать это как можно дешевле. Так может выглядеть ответ:

eyJpZCI6IjA2MTYyYzQyYmEzYjA0MTA1MDlkOGE1MjY2ZDYzMjM3LnBuZyIsInN0b3JhZ2UiOiJjYWNoZSJ9?signature=48c53039a6771d102a114ef4f093f9fa61103c327b789198c508160bc8db5952

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

Существует несколько алгоритмов, чтобы найти минимальные прямые деревья. В этом уроке мы рассмотрим алгоритм Крускала.

Что такое алгоритм Крускала

Алгоритм Крускала строит охватывающее дерево графа по одному ребру за раз. На каждом шаге алгоритма мы берем ребро с таким весом, чтобы добавление этого ребра в строящееся дерево не создавало цикла.

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

Так это выглядит (грани выделены в порядке их добавления):

eyJpZCI6IjY4ZjIxMDljMDEyNjY4N2YyMTE5NjU0Njc2ZDM0ZDg2LnBuZyIsInN0b3JhZ2UiOiJjYWNoZSJ9?signature=b2ca34f437be8c188983b8e24dc587d5a0418af862b3ecb473eb95c5f82f9676

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

Почему алгоритм Крускала работает

Разберем несколько причин, почему граф , который строит алгоритм Крускала, действительно остовное дерево графа:

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

  2. — связной граф, иначе мы могли бы добавить ребро между компонентами без цикла

  3. — охватывающий граф, который включает каждую вершину. Иначе мы могли бы добавить ребро из в вершину, которая не входит в , не вызывая цикла

  4. Мы знаем, что у деревьев на вершинах всегда ребро, поэтому нам нужно добавить ровно ребро

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

Предположим, мы попытаемся добавить в . Это создаст цикл по основным свойствам деревьев. Вдоль этого цикла должно быть еще какое-то ребро , которого нет в . — это дерево, и оно не может содержать все ребра этого цикла.

В этом примере показана гипотетическая часть вместе с и :

eyJpZCI6IjYzYTlhZjRmZDk0MjJjZDYxMWY5MDdmYWQ5MzNiMjNlLnBuZyIsInN0b3JhZ2UiOiJjYWNoZSJ9?signature=95c7ca64c8b4e5f1fe62040f318b42737c9c8037db9936259ce9b76acbc26d3e

Теперь удалим из и заменим его на — это дерево . Если просто менять одно ребро цикла на другое, все равно прямое дерево .

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

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

Выводы

Мы разобрались, что такое взвешенный граф и для чего он полезен. Также познакомились с алгоритмом Крускала, и поняли, почему он работает. Написать код, который реализует алгоритм Крускала, несложно. Самое сложное — проверить, не создает ли добавление ребра цикл. Например, это можно сделать с помощью структуры данных disjoint set.


Аватары экспертов Хекслета

Остались вопросы? Задайте их в разделе «Обсуждение»

Вам ответят команда поддержки Хекслета или другие студенты

Об обучении на Хекслете

Для полного доступа к курсу нужен базовый план

Базовый план откроет полный доступ ко всем курсам, упражнениям и урокам Хекслета, проектам и пожизненный доступ к теории пройденных уроков. Подписку можно отменить в любой момент.

Получить доступ
1000
упражнений
2000+
часов теории
3200
тестов

Открыть доступ

Курсы программирования для новичков и опытных разработчиков. Начните обучение бесплатно

  • 130 курсов, 2000+ часов теории
  • 1000 практических заданий в браузере
  • 360 000 студентов
Отправляя форму, вы принимаете «Соглашение об обработке персональных данных» и условия «Оферты», а также соглашаетесь с «Условиями использования»

Наши выпускники работают в компаниях:

Логотип компании Альфа Банк
Логотип компании Aviasales
Логотип компании Yandex
Логотип компании Tinkoff

Используйте Хекслет по-максимуму!

  • Задавайте вопросы по уроку
  • Проверяйте знания в квизах
  • Проходите практику прямо в браузере
  • Отслеживайте свой прогресс

Зарегистрируйтесь или войдите в свой аккаунт

Отправляя форму, вы принимаете «Соглашение об обработке персональных данных» и условия «Оферты», а также соглашаетесь с «Условиями использования»
Изображение Тото

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