Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.83/18: Рейтинг темы: голосов - 18, средняя оценка - 4.83
1 / 1 / 0
Регистрация: 03.09.2021
Сообщений: 46
1

Алгоритм поиска количества всех возможных путей между двумя вершинами графа на основе графа матрицы смежности

16.03.2023, 12:37. Показов 3262. Ответов 6
Метки нет (Все метки)

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


Предисловие к заданию:

Для решения задачи нужно модифицировать алгоритм обхода в глубину. Идея в том, что алгоритм запускается из какой-то из двух вершин, для которых ищется количество путей. После посещения очередной вершины, нужно проверить, не попал ли алгоритм в конечную вершину. В случае, если попал, нужно завершить обход для текущей рекурсивной ветви и увеличить количество найденных путей на единицу. Также нужно контролировать счетчик посещенных вершин visited. На каждой итерации он должен содержать набор вершин, которые присутствуют в пути на данной итерации. Имеется ввиду, что, например, когда алгоритм зашёл в тупик (у текущей вершины нет смежных непосещенных вершин), то при возвращении к предыдущей вершине текущую нужно обозначать как непосещеннуюvisited[current] = false. Таким образом в visited будут содержаться только те вершины, которые участвуют в текущем пути. В конце алгоритм должен пройти по всем возможным путям в графе.


graph.h
C++
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
#ifndef __GRAPH__
#define __GRAPH__
 
#define SIZE 10
 
class Graph {
    public:
        Graph();
        // добавление вершины
        void addVertex(int vnumber);
        // добавление ребра
        void addEdge(int v1, int v2, int weight);
        // удаление вершины
        void delVertex(int vnumber);
        // удаление ребра
        void delEdge(int v1, int v2);
        //поиск количества путей
        int findPathCount(int from, int to);
        int depthInner(int start, bool visited[], int toto, int count);
       
    private:
        bool edgeExists(int v1, int v2);
        bool vertexExists(int v);
 
        int matrix[SIZE][SIZE]; // матрица смежности
         
        int vertexes[SIZE]; // хранилище вершин
        int vertexCount; // количество добавленных вершин
};
#endif
Graph.cpp
C++
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
#include "../headers/graph.h"
 
Graph::Graph() {
    for(int i=0;i < SIZE; i++)
      for(int j=0; j< SIZE; j++)
        matrix[i][j] = 0;
    vertexCount = 0;
}
// добавление вершины
void Graph::addVertex(int vnumber)
{
    vertexes[vertexCount] = vnumber;
    vertexCount++;
}
// добавление ребра
void Graph::addEdge(int v1, int v2, int weight)
{
    matrix[v1][v2] = weight;
    matrix[v2][v1] = weight;
}
// проверка существования ребра
bool Graph::edgeExists(int v1, int v2)
{
    return matrix[v1][v2] > 0;
}
// проверка существования вершины
bool Graph::vertexExists(int v)
{
    for(int i=0;i<vertexCount;i++)
       if(vertexes[i] == v)
          return true;
    return false;
}
 
int Graph::findPathCount(int from, int to)
{
  int start=from;
  int toto=to;
  int count=0;
  bool visited[SIZE]; // список посещенных вершин
    for(int i =0; i<SIZE; i++)
       visited[i] = false; // инициализируем как не посещенные
    depthInner(start, visited, toto, count); // запуск алгоритма
  return count;
}
 
int Graph::depthInner(int start, bool visited[], int toto, int count)
{
    int count;
    std::cout << "v" << current << " -> "; // вывод текущей
    visited[start]= true; // помечаем как посещенную
    if (start==toto) {
        count++; 
    }
    else{
      for(int i=0; i<SIZE; i++){
        if(edgeExists(start,i) && !visited[i]){
            depthInner(i, visited, toto, count); // если существует ребро и вершина не посещалась, то пройдем по нему в смежную вершину
        }
      }
    }
    visited[start]= false;
    return count;
}
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
16.03.2023, 12:37
Ответы с готовыми решениями:

Алгоритм для поиска всех путей между 2 вершинами графа
Здравствуйте, возник вопрос какой алгоритм необходимо использовать для поиска всех путей, между 2...

Алгоритм для поиска всех путей между 2 вершинами графа
здраствуйте помогите написать программу

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

Написать программу которая находит количество всех путей между двумя вершинами графа
помогите пожалуйста написать программу найти количество всех путей между двумя вершинами графа с...

Количество путей между двумя вершинами графа
Здравствуйте.Я совсем недавно познакомилась с vba, так что не судите строго) задача звучит так:...

6
3696 / 2646 / 761
Регистрация: 29.06.2020
Сообщений: 9,800
16.03.2023, 14:18 2
Лучший ответ Сообщение было отмечено anastasyi как решение

Решение

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
void Graph::depthInner(int start, bool visited[], int toto, int &count)
{
    // std::cout << "v" << start << " -> "; // вывод текущей
    visited[start]= true; // помечаем как посещенную
    if (start==toto) {
        count++; 
    }
    else{
      for(int i=0; i<SIZE; i++){
        if(edgeExists(start,i) && !visited[i]){
            depthInner(i, visited, toto, count); // если существует ребро и вершина не посещалась, то пройдем по нему в смежную вершину
        }
      }
    }
    visited[start] = false;
}
Добавлено через 16 минут
Модификация с выводом этих путей :
C++
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
int Graph::findPathCount(int from, int to)
{
  int start=from;
  int toto=to;
  int count=0;
  bool visited[SIZE]; // список посещенных вершин
    for(int i =0; i<SIZE; i++)
       visited[i] = false; // инициализируем как не посещенные
  std::vector<int> path;
  depthInner(start, visited, toto, count, path); // запуск алгоритма
  return count;
}
 
void Graph::depthInner(int start, bool visited[], int toto, int &count, std::vector<int>& path)
{
    // std::cout << "v" << start << " -> "; // вывод текущей
    path.push_back(start);
    visited[start]= true; // помечаем как посещенную
    if (start==toto) {
        for(const auto v : path)
            std::cout << v << " -> ";
        std::cout << std::endl;
        count++; 
    }
    else{
      for(int i=0; i<SIZE; i++){
        if(edgeExists(start,i) && !visited[i]){
            depthInner(i, visited, toto, count, path); // если существует ребро и вершина не посещалась, то пройдем по нему в смежную вершину
        }
      }
    }
    path.pop_back();
    visited[start] = false;
}
Простой тест :
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
    Graph g;
    g.addVertex(1);
    g.addVertex(2);
    g.addVertex(3);
    g.addVertex(4);
    g.addEdge(1, 2, 1);
    g.addEdge(2, 3, 1);
    g.addEdge(3, 1, 1);
    g.addEdge(4, 1, 1);
    g.addEdge(4, 3, 1);
    std::cout << "Pathes : " << std::endl;
    int pathes_count = g.findPathCount(1, 3);
    std::cout << "Total : " << pathes_count;
1
1 / 1 / 0
Регистрация: 03.09.2021
Сообщений: 46
17.03.2023, 06:43  [ТС] 3
SmallEvil, Огромное вам спасибо! Очень сильно помогли!
0
3696 / 2646 / 761
Регистрация: 29.06.2020
Сообщений: 9,800
17.03.2023, 12:45 4
Лучший ответ Сообщение было отмечено anastasyi как решение

Решение

Цитата Сообщение от anastasyi Посмотреть сообщение
Очень сильно помогли!
Тут есть еще один нюанс.

В вашем описании задания, как то упоминается массив посещенных вершин.
И то что путь стоит брать оттуда. В конце пути, когда мы дошли к вершине назначения - в нем будут отмечены вершины по которым этот путь пройден.
Однако, порядок обхода этих вершин мы не будем знать.
Самый простой пример для иллюстрации :
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
int main()
{
    Graph g;
    g.addVertex(1);
    g.addVertex(2);
    g.addVertex(3);
    g.addVertex(4);
    g.addEdge(1, 2, 1);
    g.addEdge(1, 3, 1);
    g.addEdge(2, 3, 1);
    g.addEdge(2, 4, 1);
    g.addEdge(3, 4, 1);
    std::cout << "Pathes : " << std::endl;
    int pathes_count = g.findPathCount(1, 4);
    std::cout << "Total : " << pathes_count;
}
Код
Pathes : 
1 -> 2 -> 3 -> 4 -> 
1 -> 2 -> 4 -> 
1 -> 3 -> 2 -> 4 -> 
1 -> 3 -> 4 -> 
Total : 4
Как видим есть два пути с вершинами 1 2 3 4, но различным порядком обхода.
Это два разных пути.
Поэтому я добавил вектор, в котором мы сохраняем вершины пути.

Добавлено через 4 минуты
Цитата Сообщение от SmallEvil Посмотреть сообщение
Как видим есть два пути с вершинами 1 2 3 4, но различным порядком обхода.
Это два разных пути.
Теперь если вас спросят почему вы не брали вершины из таблицы посещений - у вас будет четкий ответ.
1
1 / 1 / 0
Регистрация: 03.09.2021
Сообщений: 46
17.03.2023, 12:56  [ТС] 5
SmallEvil, спасибо, я себе законспектирую прям)Неожиданно быстрый и четкий ответ). Но спросят врядли. там бот проверяет задания.
0
3696 / 2646 / 761
Регистрация: 29.06.2020
Сообщений: 9,800
17.03.2023, 13:02 6
Цитата Сообщение от anastasyi Посмотреть сообщение
там бот проверяет задания
Тогда будет лично для вас, для понимания.
Если проверяет бот, то добавлять/удалять/изменять сигнатуру методов графа нельзя же (только тело метода), наверное ?
Но можно добавить нужные переменные и контейнеры как поля класса.
0
1 / 1 / 0
Регистрация: 03.09.2021
Сообщений: 46
17.03.2023, 13:11  [ТС] 7
SmallEvil, можно.Там только тесты у него скрыты. Остальные файлы можно перекроить, ну по идее можно и тестируемые данные вывести вначале из майна. но это и не важно. главное чтобы алгоритм сам работал. Что-то тяжело алгоритмы мне даются..
0
17.03.2023, 13:11
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
17.03.2023, 13:11
Помогаю со студенческими работами здесь

Поиск кратчайших путей между двумя вершинами графа методом Шимбела.
Доброго всем время суток!! В универе задали на РГР написать программу в С++, которая находит ...

Алгоритм поиска все путей между двумя вершинами в графе
Найти пути, соединяющие две вершины заданного ориентированного графа. Помогите, пожалуйста,...

Написать предикат поиска всех путей в ориентированном графе между двумя заданными вершинами
Есть задача: Написать предикат поиска всех путей в ориентированном графе между двумя заданными...

Количество различных путей между всеми вершинами графа
Здравствуйте! Имеется граф, заданный матрицей смежности, реализованной в виде двумерного...

Реализовать поиск кратчайших путей между вершинами графа
ПОМОГИТЕ ПОЖАЛУСТА! Реализовать поиск кратчайших путей между вершинами графа.

Постройте матрицу кратчайших путей между вершинами графа
Флойд – 1 Полный ориентировочный взвешенный граф задан матрицей смежности. Постройте матрицу...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
7
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru