Графы. Алгоритм Прима

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

Чтобы понять что такое ребро, вес смотрим рисунок
Граф
Вершины графа на этом рисунке обозначены кружками.
Номер вершины — цифра в кружке.
Ребро — отрезок, соединяющий вершины
Вес ребра — синяя цифра над отрезком.

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

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

  • На рисунке изображено мысленное дополнение неполного графа до полного.

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

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

Созданная матрица смежности для нарисованного графа

∞      10      ∞      ∞
10     ∞       9      20
∞      9        ∞      15
∞      20      15     ∞

В дальнейшем под бесконечностью будет число, которое компилятор воспринимает как максимальное.

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

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

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

Алгоритм Прима

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

Пример работы

Алгоритм Прима Алгоритм Прима

21 комментарий на «“Графы. Алгоритм Прима”»

  1. Евгений:

    Почему матрица смежности первого рисунка, вершина 2-2 бесконечность? Нельзя из 2 в 2 попасть по пути 2->4->3->2? И будет сумма веса рёбер, которую мы запишем в матрицу смежности.

    • Арсений:

      Потому что прямого пути из 2 в 2 нет. Матрица инцидентности подразумевает под собой написание именно прямых путей.

  2. Фелагунд:

    Условие if(visited[i]!=0) во вложенном цикле при поиске ребра с наименьшим весом лучше переместить во внешний цикл сразу после for(i=1,min=999;i<=n;i++)

    Гораздо оптимальней

  3. Карим:

    в коде есть недароботки, например вы не определяете возможно ли вообще соединить все вершины или нет

  4. Михаил:

    У меня выдает ошибку «С2872 неоднозначный символ min». Если изменить имя переменной, то я не знаю, где какую вставить… Что посоветуете?

    • Заменить все min на min_

      Это произошло, потому что в STL есть функция min, которая сравнивает два значения и возвращает наименьшее. А в коде использована одноимённая переменная. Компилятор поэтому не врубился. В этих случаях просто меняются имена переменных.

      • Михаил:

        действительно! Но теперь не могу понять, почему была проблема. Можете объяснить? И почему «_» все решило?

        • Олег:

          Ну, компилятору не понятно имел ты в виду min() как функцию или как переменную — вот он и пишет о неоднозначности. Добавлением «_» вы четко отделяете имя переменной от функции.

  5. Михаил:

    Все. Сам разобрался, почему так было ) Спасибо за помощь! Давно на этом сайте занимаюсь.

  6. Илья:

    Сколько максимально вершин можно вбить?

  7. Аноним:

    не правильно выводит для теста:

    4

    0 1 0 0

    0 0 2 0

    0 0 0 5

    4 0 0 0

    выводит 8, а должен 7

    не все варианты смотрит

  8. Shel:

    Может быть потому что у вас не матрица смежности, не?))

    • Олег:

      Там что-то типа опечатки. Скорее всего имелась в виду матрица расстояний, ибо в том же примере вводятся не нули и единицы, как в матрице смежности, а вес ребёр

  9. alalala:

    почему все переменные глобальные? что за жесть?

  10. big_boss:

    Здравствуйте. Скажите пожалуйста блок-схема, которая содержится по ссылке http://www.mathros.net.ua/algorytm-pryma.html подходит для размещенной Вами программы или нет? Блок -схему нашел, а с реализацией не очень получается.

    • Не могу точно ответить. Я не знаком с блок-схемами, чтобы что-то о них утверждать.

      • big_boss:

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

  11. Дима:

    cannot bind ‘std::istream {aka std::basic_istream}’ lvalue to ‘std::basic_istream&&’
    In file included from /usr/include/c++/4.9/iostream: Выдает данную ошибку если ввести в код.

    • 1. Какой компилятор используете?
      2. Какой код туда пишете?

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

      У меня работает:

      Если использовать using namespace std, то с переменной min могут возникнуть проблемы, нужно будет её называть иначе.

  12. doni1:

    как сделать чтобы виводило макс стоимость ?

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Поиск

 
     

Случайная книга в электронном формате

https://www.litres.ru/maks-shlee/qt-5-3-professionalnoe-programmirovanie-na-c-19236076/?lfrom=15589587
Яндекс.Метрика