Чтобы понять что такое ребро, вес смотрим рисунок
Вершины графа на этом рисунке обозначены кружками.
Номер вершины — цифра в кружке.
Ребро — отрезок, соединяющий вершины
Вес ребра — синяя цифра над отрезком.
Проще всего представить вес ребра как длина пути от одной вершины графа до другой, но это может быть и стоимость и скорость и что угодно. Например вершины графа могут быть городами, а вес ребер скоростью, с которой спортсмен сможет добежать из одного города в другой или же можно представить что, ребра -это дороги, а их вес — это стоимость для постройки. Так вот, алгоритм Прима позволяет определить минимальные (максимальные) затраты для соединения каждой из необходимых вершин.
Чтобы определить минимальные затраты для необходимых вершин, нужно для всех не требуемых вершин представить путь как максимально длинный и мысленно дополнить граф до полного. Согласно теоремам из дискретной математики — любой неполный граф можно дополнить до полного, поэтому те ребра, которые добавляем к графу будут иметь длину, стремящуюся к бесконечности. Чем больше — тем лучше. Это нужно для того, чтоб правильно выискивать минимальные веса ребер.
Чтобы искать максимальную оценку маршрута, нужно взять минимальное значение, т.е. это будет (минус Бесконечность), но я буду опсиывать алогритм для минимальной оценки.
Чтобы компьютер смог использовать алгоритм на графе, нужно этот граф перевести в понятный компьютеру вид — в цифры. Чтобы это сделать, составляют или матрицу смежности или матрицу инцендентности.
Показать алгоритм заполнения матрицы смежности
Созданная матрица смежности для нарисованного графа
∞ 10 ∞ ∞
10 ∞ 9 20
∞ 9 ∞ 15
∞ 20 15 ∞
В дальнейшем под бесконечностью будет число, которое компилятор воспринимает как максимальное.
1 |
unsigned int inf=-1; // Беззнаковый -1 = максимальное число для типа int |
На разных машиеах int может иметь разный размер, поэтому на одном ПК может быть один максимум, на другом другой, но это к сведению, а к теме не относится.
А к теме относиться понимание алгоритма Прима. Если вы его понимаете — то это просто великолепно и значит своими силами вполне способны написать программу для его выполнения, если же не понимаете, то придется помучаться и понять теорию.
Для лучшего понимания этой статьи хорошо бы знать, что такое остовное дерево Минимальное остовное дерево
Вот замечательно показанные примеры теоритического выполнения некоторых алгоритмов на графах. Среди этих примеров есть пример работы алгоритма Прима Минимальные остовные деревья
Если кому-то покажется, что этого мало, то вот мое личное художество, анимированный рисунок, только немного не того графа, который я описывал выше. Я посчитал, что тот граф не очень подходит для иллюстрации расчетов, поэтому немного изменил веса ребер.
А вот пример реализации алгоритма Прима, правда пример не мой, поэтому я особо его не смогу прокомментировать. Но, несмотря на это, этот пример не должен быть очень сложным для его понимания.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 |
#include<conio.h> #include<iostream.h> int a,b,u,v,n,i,j,ne=1; int visited[10]={0},min,mincost=0,cost[10][10]; void main() { int path[100]={0}; //В этот массив будут записываться вершины, по которым составиться путь int path_index=0; clrscr(); cout<<"Введи количество вершин "; cin>>n; cout<<"Введи матрицу смежности\n"; for(i=1;i<=n;i++) for(j=1;j<=n;j++) { cin>>cost[i][j]; if(cost[i][j]==0) cost[i][j]=999; //999 - это что-типа бесконечности. Должно быть больше чем значения веса каждого из ребер в графе } visited[1]=1; cout<<"\n"; while(ne < n) { for(i=1,min=999;i<=n;i++) for(j=1;j<=n;j++) if(cost[i][j]< min) if(visited[i]!=0) { min=cost[i][j]; a=u=i; b=v=j; } if(visited[u]==0 || visited[v]==0) { path[path_index]=b; path_index++; //cout<<"\n "<<ne++<<" "<<a<<" "<<b<<min; //Можно вывести так ne++; //если строчку выше раскомментировать - эту закомментировать mincost+=min; visited[b]=1; } cost[a][b]=cost[b][a]=999; } cout<<"\n"; cout<<1<<" --> "; for (int i=0;i<n-1;i++) { cout<<path[i]; if (i<n-2) cout<<" --> "; } cout<<"\n Минимальная стоимость "<<mincost; cin.get(); cin.get(); } |
Пример работы
Почему матрица смежности первого рисунка, вершина 2-2 бесконечность? Нельзя из 2 в 2 попасть по пути 2->4->3->2? И будет сумма веса рёбер, которую мы запишем в матрицу смежности.
Потому что прямого пути из 2 в 2 нет. Матрица инцидентности подразумевает под собой написание именно прямых путей.
Условие if(visited[i]!=0) во вложенном цикле при поиске ребра с наименьшим весом лучше переместить во внешний цикл сразу после for(i=1,min=999;i<=n;i++)
Гораздо оптимальней
в коде есть недароботки, например вы не определяете возможно ли вообще соединить все вершины или нет
У меня выдает ошибку «С2872 неоднозначный символ min». Если изменить имя переменной, то я не знаю, где какую вставить… Что посоветуете?
Заменить все min на min_
Это произошло, потому что в STL есть функция min, которая сравнивает два значения и возвращает наименьшее. А в коде использована одноимённая переменная. Компилятор поэтому не врубился. В этих случаях просто меняются имена переменных.
действительно! Но теперь не могу понять, почему была проблема. Можете объяснить? И почему «_» все решило?
Ну, компилятору не понятно имел ты в виду min() как функцию или как переменную — вот он и пишет о неоднозначности. Добавлением «_» вы четко отделяете имя переменной от функции.
Все. Сам разобрался, почему так было ) Спасибо за помощь! Давно на этом сайте занимаюсь.
Сколько максимально вершин можно вбить?
Я не знаю.
не правильно выводит для теста:
4
0 1 0 0
0 0 2 0
0 0 0 5
4 0 0 0
выводит 8, а должен 7
не все варианты смотрит
Может быть потому что у вас не матрица смежности, не?))
Там что-то типа опечатки. Скорее всего имелась в виду матрица расстояний, ибо в том же примере вводятся не нули и единицы, как в матрице смежности, а вес ребёр
почему все переменные глобальные? что за жесть?
Здравствуйте. Скажите пожалуйста блок-схема, которая содержится по ссылке http://www.mathros.net.ua/algorytm-pryma.html подходит для размещенной Вами программы или нет? Блок -схему нашел, а с реализацией не очень получается.
Не могу точно ответить. Я не знаком с блок-схемами, чтобы что-то о них утверждать.
Понятно. Спасибо за то, что ответили на мой комментарий. Придется пытаться реализовать программу самому.
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 могут возникнуть проблемы, нужно будет её называть иначе.
как сделать чтобы виводило макс стоимость ?