Краткая постановка задания

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

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

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

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

Стоимость доработки программы

Ниже приведена стоимость доработки программы:

ОперацияКонсольный форматВизуальный формат
1.Построение матрицы смежности.$150$ рублей$300$ рублей
2.Построение матрицы инциденций.$150$ рублей$300$ рублей
3.Построение перечней ребер.$180$ рублей$300$ рублей
4.Построение списков связи.$150$ рублей$300$ рублей
5.Построение остовного дерева путем обхода в глубину.$300$ рублей$400$ рублей
6.Построение остовного дерева путем обхода в ширину.$300$ рублей$400$ рублей
7.Построение каркаса минимальной стоимости (алгоритм Краскала).$600$ рублей$800$ рублей
8.Построение каркаса минимальной стоимости (алгоритм Прима).$600$ рублей$800$ рублей
9.Поиск и построение Эйлеров цикла в графе.$700$ рублей$1\ 000$ рублей
10.Построение массива кратчайших путей алгоритмом Дейкстры.$500$ рублей$700$ рублей
11.Построение матрицы кратчайших путей алгоритмом Флойда.$600$ рублей$800$ рублей

Данная работа предполагает написание программы на языке C++. При заказе нужных вам операций с графом вы получите качественно написанную и хорошо прокомментированную программу.

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

Варианты индивидуальных заданий и их стоимость реализации

ВАЖНО!

  • Задания обладают неодинаковой сложностью. Есть достаточно нетривиальные операции, требующие кодирования дополнительных функций.
  • Стоимость каждой операции обозначена в таблице ниже в самой правкой колонке «Стоимость».
Формулировка заданияСтоимость
1Найти самый длинный простой путь в графе (путь, все ребра которого попарно различны)$600$ рублей
2Найти медиану взвешенного графа, т е такую вершину, сумма расстояний от которой до всех других вершин минимальна.$600$ рублей
3Задана система односторонних дорог. Найти путь, соединяющий города $A$ и $B$ и не проходящий через заданное множество городов.$500$ рублей
4Определить, изоморфен ли заданный граф своему дополнению.$800$ рублей
5Мостом графа назовем такое ребро, удаление которого увеличивает число компонент связности графа. Найти все мосты для заданного графа.$500$ рублей
6Найти длину самого длинного простого пути от города $A$ до города $B$ в заданной системе односторонних дорог.$500$ рублей
7В заданном графе найти максимальный по количеству вершин полный подграф.$800$ рублей
8Задан ориентированный граф с $N$ ($1 \leq N \leq 10$) вершинами, пронумерованными целыми числами от $1$ до $N$. Напишите программу, которая подсчитывает количество различных путей между всеми парами вершин графа.$600$ рублей
9Необходимо добраться на самолете из города $A$ в город $B$ при условии, что между ними нет прямого авиационного сообщения, затратив при этом минимальные средства. Заданы возможные промежуточные аэропорты. Для каждой пары аэропортов известно, существует ли между ними прямой маршрут, и если да, то известна минимальная стоимость перелета по этому маршруту.$600$ рублей
10Даны два числа: $N$ и $M$. Построить граф из $N$ вершин и $M$ ребер. Каждой вершине ставится в соответствие число ребер, входящих в нее. Граф должен быть таким, чтобы сумма квадратов этих чисел была минимальна.$700$ рублей
11По заданной системе односторонних дорог определить, есть ли в ней город, куда можно попасть из любого другого города, проезжая не более $100$ км.$500$ рублей
12В графе найти максимальное (по количеству ребер) подмножество попарно несмежных ребер.$700$ рублей
13Определить, является ли заданный граф двудольным.$800$ рублей
14По системе двусторонних дорог определить, можно ли, построив какие-нибудь три новые дороги, из заданного города добраться до каждого из остальных городов, проезжая не более $100$ км.$600$ рублей
15Некоторые школы связаны компьютерной сетью. Между школами заключены соглашения: каждая школа имеет список школ-получателей, которым она рассылает программное обеспечение всякий раз, получив новое бесплатное программное обеспечение (извне сети или из другой школы). При этом, если школа $B$ есть в списке получателей школы $A$, то школа $A$ может не быть в списке получателей школы $B$. Требуется написать написать программу, определяющую минимальное количество школ, которым надо передать по экземпляру нового программного обеспечения, чтобы распространить его по всем школам сети в соответствии с соглашениями.$800$ рублей
16Известно, что заданный граф — не дерево. Проверить, можно ли из него получить дерево путем удаления $n$ вершин (каждая вершина удаляется вместе с инцидентными ей ребрами, $n$ вводится с клавиатуры).$700$ рублей
17Задан неориентированный граф. При прохождении по некоторым ребрам некоторые (определенные заранее) ребра могут исчезать или появляться. Найти кратчайший путь из вершины с номером $q$ в вершину с номером $w$.$800$ рублей
18

Дан ориентированный граф с $N$ вершинами ($N \le 50$). Вершины и дуги окрашены в цвета с номерами от $1$ до $M$ ($M \leq 6$). Указаны две вершины, в которых находятся фишки игрока, и конечная вершина.

Правила перемещения фишек:

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

Игра заканчивается, если одна из фишек достигает конечной вершины. Написать программу поиска кратчайшего пути до конечной вершины, если он существует.

$800$ рублей
19Заданы два числа: $N$ и $M$ ($20 \leq M \leq N \leq 150$), где $N$ — количество точек на плоскости. Требуется построить дерево из $M$ точек так, чтобы оно было оптимальным. Дерево называется оптимальным, если сумма всех его ребер минимальна. Все ребра — расстояния между вершинами, заданными координатами точек на плоскости.$700$ рублей
20Треугольником в неориентированном графе называется тройка вершин, попарно соединенных дугами. Склеиванием треугольника называется операция замены вершин треугольника новой вершиной с сохранением всех связей с остальными вершинами графа. Дан неориентированный граф. Склейте все треугольники графа.$700$ рублей
21Проверить, является ли заданный ориентированный граф связным.Бесплатно (см.пример ниже)

Лабораторная работа $№4$ предполагает написание программы на языке C++. При заказе работы своего варианта вы получите качественно написанную и хорошо прокомментированную программу.

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

Образец выполнения (вариант №21)

Условие задания

Проверить, является ли заданный ориентированный граф связным.

Алгоритм решения задачи

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

 ➡  Если граф является ориентированным, то можно говорить о нескольких вариантах его связности:

  • Ориентированный граф называется сильно-связным, если в нем существует путь из произвольной вершины в любую другую произвольную вершину.
  • Ориентированный граф называется слабо-связным, если является связным неориентированный граф, полученный из него заменой ориентированных ребер неориентированными.

Составители заданий ни слова не упомянули про данную тонкость, поэтому нам придется самим определиться, с каким типом связности работать.

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

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

Пример входного текстового файла с данными и визуализация графа, построенного на основании этих данных:САФУ. Практикум на С++ (Латухина). Лабораторная работа №4 (графы). Входной текстовый файл с данными

➡ Является ли представленный выше ориентированный граф связным? Чтобы ответить на этот вопрос, нам нужно проверить необходимое и достаточное условие связности графа:

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

Так как граф является ориентированным, то придется последовательно перебирать все его вершины! Потому что, если, например, мы смогли посетить вершину $№6$ из вершины $№5$, то это не гарантирует обратного.

Для обхода графа в основном применяются два классический алгоритма:

  • Обход графа в ширину (в теории англ. BFS, Breadth-First-Searh).
  • Обход графа в глубину (в теории англ. DFS, Depth-First-Search).

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

Если у вас есть какие-то сложности с понимаем того, как устроены данные алгоритмы обхода графа, то можете записаться на частные занятия по программированию к репетитору
$\rightarrow$ Александру Георгиевичу (№тел.: $8(926) 610 — 61 — 95$).

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

 ➡ Алгоритм обхода графа в ширину задействует такую структуру данных, как очередь, а алгоритм обхода графа в глубину — стек. Возьмем за базу алгоритм DFS, использующий стек. Кстати, в лабораторной работе №2 были закодированы, как стек, так и очередь. Частично тем кодом можно воспользоваться при программировании данного задания. Но лишь частично!

Заданный граф состоит из $6$ вершин. Чтобы проверить ориентированный граф на связность, запустим последовательно алгоритм DFS (обход в глубину) из каждой его вершины.

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

№ старт. вершиныСхема посещения вершин графаСвязность?
1САФУ. Практикум на С++ (Латухина). Лабораторная работа №4 (графы). Посещение вершин графа с вершины №1, используя DFSпринято
2САФУ. Практикум на С++ (Латухина). Лабораторная работа №4 (графы). Посещение вершин графа с вершины №2, используя DFSпринято
3САФУ. Практикум на С++ (Латухина). Лабораторная работа №4 (графы). Посещение вершин графа с вершины №3, используя DFSпринято
4САФУ. Практикум на С++ (Латухина). Лабораторная работа №4 (графы). Посещение вершин графа с вершины №4, используя DFSпринято
5САФУ. Практикум на С++ (Латухина). Лабораторная работа №4 (графы). Посещение вершин графа с вершины №5, используя DFSпринято
6САФУ. Практикум на С++ (Латухина). Лабораторная работа №4 (графы). Посещение вершин графа с вершины №6, используя DFSпринято

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

А теперь давайте из представленного графа удалим буквально одну связь/дугу между вершинами $№3$ и $№2$. И запустим алгоритм обхода DFS из вершины $№5$.САФУ. Практикум на С++ (Латухина). Лабораторная работа №4 (графы). Посещение вершин графа с вершины №5, используя DFS. Граф является несвязным!

Как видите, результаты неутешительны, связность графа стала нарушена — он стал несвязным ориентированным графом! Теперь граф обладает больше одной компонентой связности. А достаточно было убрать всего лишь одну дугу…

В итоге, чтобы студент мог безболезненно правильно закодировать подобную задачу, он должен хорошо понимать:

  • Принцип работы одномерных и двухмерных динамических массивов.
  • Принцип работы динамической структуры данных стек.
  • Принцип правильного конструирования программного обеспечения (разделение подзадач на отдельные функции).
  • Принцип работы обхода графа в глубину (DFS).
  • Как взаимодействовать с текстовыми файлами, используя файловые потоки.

Перечень пользовательских программных функций

Для решения поставленной задачи пришлось разработать следующие программные функции ($12$ штук):

Смысл операцииНазвание функции в коде
1.Создание элемента стека.TElem* CreateElem(const int pinf)
2.Добавление элемента в стек (в вершину стека).void Push(const int pinf)
3.Получение значения элемента на вершине стека (не удаляя сам элемент).int Peek(void)
4.Удаление элемента из вершины стека.void Pop(void)
5.Выделение памяти под динамическую матрицу смежности графа.int** CreateMatrix(const int psize)
6.Вывод матрицы смежности графа на экран.void PrintMatrix(int** pmatrix, const int psize)
7.Заполнение матрицы смежности графа данными из заданного текстового файла.int** ReadMatrixFromTextFile(const string pnameFile, int& psize)
8.Освобождение памяти из-под динамической матрицы смежности графа.void DestroyMatrix(int** pmatrix, const int psize)
9.Обход неориентированного графа в глубину (с использованием структуры данных стек, нерекурсивный алгоритм).bool DFS(int** pmatrix, const int psize, const int pstartVertex, bool pvisited[])
10.Установка всем вершинам графа статуса «посещена / не посещена».void SetStatusVertex(bool pvisited[], const int psize, const bool pstatus)
11.Проверка ориентированного графа на связность.void IsConnectedGraph(int** pmatrix, const int psize)
12.Главная функция программы (точка входа).int main(void)

Реализация задачи на языке С++

 

Результаты работы программы

ГрафРезультат
1САФУ. Практикум на С++ (Латухина). Лабораторная работа №4 (графы). Тест №1. Визуальное представление связного графа, состоящего из 6 вершинСАФУ. Практикум на С++ (Латухина). Лабораторная работа №4 (графы). Тест №1. Граф состоит из 6 вершин и является связным
2САФУ. Практикум на С++ (Латухина). Лабораторная работа №4 (графы). Тест №1. Визуальное представление несвязного графа, состоящего из 6 вершинСАФУ. Практикум на С++ (Латухина). Лабораторная работа №4 (графы). Тест №1. Граф состоит из 6 вершин и является несвязным
3САФУ. Практикум на С++ (Латухина). Лабораторная работа №4 (графы). Тест №1. Визуальное представление связного графа, состоящего из 4 вершинСАФУ. Практикум на С++ (Латухина). Лабораторная работа №4 (графы). Тест №1. Граф состоит из 4 вершин и является связным