
6. Приложение №2. Текст программы.
#include <iostream>
#include <vector>
#include <time.h>
#include <algorithm>
using namespace std;
//Структура "ребро"
struct line
{
//Начало ребра, конец ребра и вес ребра
int a, b, weight;
};
//Структура "вершина"
struct point
{
vector<line> lines;//Список ребер, выходящих из вершины
bool flag;//Определяет, посещена ли вершина
};
void printGraph(int **mas, int size)
{
cout << endl;
for(int i = 0; i < size; i++)
{
for(int j = 0; j < size; j++)
{
cout << mas[i][j] << " ";
}
cout << endl;
}
}
int random(int min, int max)
{
return min + (rand() % (int)(max - min + 1));
}
//ТЕСТ ПРОВОДИЛСЯ НА ЭТОМ МАССИВЕ
//{ 0, 2, 2, 0}
//{ 2, 0, 0, 3}
//{ 2, 0, 0, 1}
//{ 0, 3, 1, 0}
int main()
{
srand(time(NULL)); //Включаем генерацию случайного числа на основании текущего времени
int Vcount = -1; //Кол-во вершин графа
int Lcount = -1; //Кол-во ребер графа
int **graphArr; //Двумерный массив вершин и расстояний между ними(что-то типа матрицы смежности. не помню, как правильно называется)
point *points; //Массив вершин с указанием ребер, которые исходят из соответствующей вершины
setlocale(LC_ALL, "Russian");
cout << endl << "Введите количество вершин в графе (число, большее единицы) : ";
do
{
cin >> Vcount;
}
while(Vcount <= 1);
//Создаем матрицу смежности и заполняем её нулями
points = new point[Vcount];
graphArr = new int*[Vcount];
for(int i = 0; i < Vcount; i++)
{
graphArr[i] = new int[Vcount];
}
for(int i = 0; i < Vcount; i++)
{
for(int j = 0; j < Vcount; j++)
{
graphArr[i][j] = 0;
}
}
do
{
//Считываем ребра и записываем в матрицу
cout << endl << "Введите количество ребер.\n"
<< "Внимание : чтобы построить путь, необходимо, чтобы граф имел одну компоненту связности. Поэтому количество ребер\n"
<< "должно быть не менее, чем " << Vcount - 1 << endl;
do
{
cin >> Lcount;
}
while(Lcount < Vcount - 1);
}
while(Lcount < 1);
cout << endl
<< "Введите название и вес каждого ребра в виде : <вершина1> <вершина2> <вес>\nНумерация вершин начинается с единицы!)"
<< endl;
for(int i = 0; i < Lcount; i++)
{
int a, b, weight;
cout << endl << "\tРебро" << i + 1 << " : ";
cin >> a >> b >> weight;
graphArr[a - 1][b - 1] = weight;
graphArr[b - 1][a - 1] = weight;
}
//Создаем массив вершин из матрицы смежности
points = new point[Vcount];
for(int i = 0; i < Vcount; i++)
{
for(int j = 0; j < Vcount; j++)
{
if(graphArr[i][j] != 0)
{
line temp;
temp.a = i;
temp.b = j;
temp.weight = graphArr[i][j];
points[i].lines.push_back(temp);
points[i].flag = false;
}
}
}
vector<point> path;//здесь будет храниться путь
int cp = random(0, Vcount - 1);
int SUM = 0;
path.push_back(points[cp]);
points[cp].flag = true;
while(path.size() != Vcount)
{
//Найдем кратчайшее ребро. Для этого пройдем по всем вершинам, уже включенным в путь и переберем их ребра.
//Для каждой вершины найдем свое кратчайшее ребро, затем сравним кратчайшие ребра из всех вершин, включенных в путь и
//выберем минимальное из них. Далее, будем смотреть в какую вершину приведет нас это ребро. Перейдем в эту вершину, пометив
//её как пройденную и повторим действия.
line global_min_line; // <-- наше искомое кратчайшее ребро
global_min_line.weight = 100000000; // вес минимального ребра
int psize = path.size();
for(int pit = 0; pit < psize; pit++)
{
line local_min_line; // <-- кратчайшее ребро для текущей вершины
local_min_line.weight = 100000000; // вес текущего минимального ребра
int lsize = path[pit].lines.size();
for(int lit = 0; lit < lsize; lit++)
{
//если нашлось ребро легче, то текущему минимальному ребру присваиваем его параметры
//также проверим, не ведет ли это ребро в уже пройденную вершину. В этом случае игнорируем его.
if(path[pit].lines[lit].weight < local_min_line.weight && !points[path[pit].lines[lit].b].flag)
{
local_min_line.a = path[pit].lines[lit].a;
local_min_line.b = path[pit].lines[lit].b;
local_min_line.weight = path[pit].lines[lit].weight;
}
}
if(local_min_line.weight < global_min_line.weight)
global_min_line = local_min_line;
}
//Добавляем в путь ту вершину, которой кончается кратчайшее ребро
path.push_back(points[global_min_line.b]);
points[global_min_line.b].flag = true;
SUM += global_min_line.weight;
}
//Вывод на экран результатов (кратчайший путь и стоимость пути)
cout << endl << "path : ";
for(int i = 0; i < path.size() - 1; i++)
cout << path[i].lines[0].a + 1 << "-->";
cout << path[path.size() - 1].lines[0].a + 1 << endl;
cout << endl << "cost = " << SUM << endl;
system("pause");
return 0;
}