Kwwiker

5 SiAOD

Nov 21st, 2021
54
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 11.31 KB | None | 0 0
  1. #include <iostream>
  2. #include <vector>
  3. #include <string>
  4.  
  5. using namespace std;
  6.  
  7. class Graph {
  8. private:
  9.     int n; // Кол-во узлов
  10.     int** matrix; // Матрица смежностей
  11.     vector<string> chains; // Вектор простых цепочек графа
  12.  
  13. public:
  14.     // Создаём объект класса граф
  15.     Graph(int n) {
  16.         this->n = n; // Передаём количесвто узлов
  17.  
  18.         // Создаём матрицу смежностей
  19.         matrix = new int* [n + 1];
  20.         for (int i = 0; i <= n; i++) {
  21.             matrix[i] = new int[n + 1];
  22.             for (int j = 0; j <= n; j++) {
  23.                 matrix[i][j] = 0; // Заполняем матрицу 0
  24.             }
  25.         }
  26.     }
  27.  
  28.     // Метод добавления не взвешенного ребра
  29.     void addEdge(int first, int second) {
  30.         matrix[first][second] = 1; // Присваиваем новому ребру между узлами first и second в матрице смежности вес равный 1
  31.     }
  32.  
  33.     // Метод добавления взвешенного ребра
  34.     void addEdgeWithWeight(int first, int second, int weight) {
  35.         matrix[first][second] = weight; // Присваиваем новому ребру между узлами first и second в матрице смежности переданный вес
  36.     }
  37.  
  38.     // Метод заполнения не взвешенного графа
  39.     void fillGraph() {
  40.         string temp;
  41.     EDGE1:
  42.         cout << "Do you want enter new edge? (y/n) "; // Спрашиваем будет ли пользователь вводить новое ребро
  43.         cin >> temp; // пользователь отвечает на вопрос
  44.         if (temp != "y" && temp != "n") {
  45.             cout << "Try again" << endl;
  46.             goto EDGE1;
  47.         }
  48.         else if (temp == "y") { // если, да
  49.             int first, second;
  50.             cout << "Enter edge:" << endl;
  51.             cout << "first node: ";
  52.             cin >> first; // то вводит первый узел
  53.             cout << "second node: ";
  54.             cin >> second; // вводит второй узел
  55.             addEdge(first, second); // добавляем новое не взвешенное ребро
  56.             goto EDGE1; // повторяем алгоритм
  57.         }
  58.     }
  59.  
  60.     // Метод заполнения взвешенного графа
  61.     void fillGraphWithWeight() {
  62.         string temp;
  63.     EDGE2:
  64.         cout << "Do you want enter new edge? (y/n) "; // Спрашиваем будет ли пользователь вводить новое ребро
  65.         cin >> temp; // пользователь отвечает на вопрос
  66.         if (temp != "y" && temp != "n") {
  67.             cout << "Try again" << endl;
  68.             goto EDGE2;
  69.         }
  70.         else if (temp == "y") { // если, да
  71.             int first, second, weight;
  72.             cout << "Enter edge:" << endl;
  73.             cout << "first node: ";
  74.             cin >> first; // то вводит первый узел
  75.             cout << "second node: ";
  76.             cin >> second; // вводит второй узел
  77.             cout << "weight: ";
  78.             cin >> weight; // вводит вес
  79.             addEdgeWithWeight(first, second, weight); // добавляем новое взвешенное ребро
  80.             goto EDGE2; // повторяем алгоритм
  81.         }
  82.     }
  83.  
  84.     // Метод вывода графа как матрицы смежностей
  85.     void printMatrix() {
  86.         if (n > 0) { // Если матрица существует
  87.             cout << "Matrix:" << endl;
  88.             for (int i = 1; i <= n; i++) {
  89.                 for (int j = 1; j <= n; j++) {
  90.                     cout << matrix[i][j] << "\t"; // Выводим вес ребра между узлами i и j
  91.                 }
  92.                 cout << endl;
  93.             }
  94.         }
  95.     }
  96.  
  97.     // Метод вывода графа как списка смежностей
  98.     void printList() {
  99.         if (n > 0) { // Если есть хотя бы один узел
  100.             cout << "List:" << endl;
  101.             for (int i = 1; i <= n; i++) { // Перебираем все узлы
  102.                 cout << i << ": "; // Выводим номер узла
  103.                 for (int j = 1; j <= n; j++) { // Перебираем все узлы
  104.                     if (matrix[i][j] > 0) { // Проверяем на смежность
  105.                         cout << j << " "; // Выводим смежные узлы
  106.                     }
  107.                 }
  108.                 cout << endl;
  109.             }
  110.         }
  111.     }
  112.  
  113.     // Метод сохранения и вывода цепочки
  114.     void saveChain(vector<int> chain) {
  115.         string ch = ""; // Создаём строку, в которую занесём цепочку
  116.         for (int node : chain) {
  117.             ch += to_string(node) + "-"; // Записываем цепочку в строку из вектора
  118.         }
  119.         ch.pop_back(); // Убираем лишнее "-" в конце
  120.  
  121.         string rch = ""; // Создаём строку для перевёрнутой цепочки
  122.         for (int i = 0; i < ch.length(); i++) {
  123.             rch += ch[ch.length() - 1 - i]; // Перевораичваем цепочку и записываем в созданную переменную
  124.         }
  125.  
  126.         if (find(chains.begin(), chains.end(), rch) == chains.end()) { // Цепочка и перевёрнутая цепочка считаются за одну и ту же цепочку
  127.             chains.push_back(ch); // Если ещё не записывали перевёрнутую, то записываем текущую
  128.             cout << ch << endl; // и выводим её
  129.         }
  130.     }
  131.  
  132.     // Преобразованный для поиска всех цепочек в графе метод поиска "в глубину" (DFS)
  133.     // Простая цепочка - любой путь, который не включает в себя один и тот же узел дважды
  134.     void dfs(int i, vector<int> chain) {
  135.         chain.push_back(i); // Добавляем узел в цепочку
  136.  
  137.         for (int j = 1; j <= n; j++) { // Перебираем все узлы
  138.             if (matrix[i][j] > 0) { // Проверяем каждый на смежность с текущим
  139.                 if (find(chain.begin(), chain.end(), j) == chain.end()) { // Проверяем, что ещё не проходили, через вершину
  140.                     dfs(j, chain); // Рекурсивно вызываем DFS
  141.                 }
  142.             }
  143.         }
  144.  
  145.         if (chain.size() > 1) { // Если в цепочке больше 1 узла
  146.             saveChain(chain); // Сохраняем её
  147.         }
  148.     }
  149.  
  150.     // Метод поиска всех цепочек в графе
  151.     void showAllChains() {
  152.         for (int i = 1; i <= n; i++) { // Перебираем все узлы
  153.             vector<int> chain; // Создаём вектор цепочки
  154.             dfs(i, chain); // Начинаем преобразованный поиск "в глубину"
  155.         }
  156.     }
  157.  
  158.     // Метод нахождения кратчайшего пути методом Флойда
  159.     void minWayByFloyd(int first, int second) {
  160.         int INF = 1000000; // Большое число/бесконечность
  161.  
  162.         // Создаём матрицу длин кратчайших путей и матрицу детей ("серединных" узлов между искомыми узлами) для прохождения по кратчайшему пути для каждой пары узлов
  163.         int** minWay = new int* [n + 1];
  164.         int** children = new int* [n + 1];
  165.         for (int i = 0; i <= n; i++) {
  166.             minWay[i] = new int[n + 1];
  167.             children[i] = new int[n + 1];
  168.             for (int j = 0; j <= n; j++) {
  169.                 if (matrix[i][j] == 0) { // Если нет прямого пути между узлами
  170.                     minWay[i][j] = INF; // то записываем большое число (INF)
  171.                     children[i][j] = 0; // а сюда 0
  172.                     continue;
  173.                 }
  174.                 minWay[i][j] = matrix[i][j]; // иначе записываем вес
  175.                 children[i][j] = j; // и пункт назначения
  176.             }
  177.         }
  178.  
  179.         // Реализуем метод Флойда
  180.         for (int k = 1; k <= n; k++) {
  181.             for (int i = 1; i <= n; i++) {
  182.                 for (int j = 1; j <= n; j++) {
  183.                     if (i != j && k != i && k != j && minWay[i][k] < INF && minWay[k][j] < INF) {
  184.                         if (minWay[i][j] > minWay[i][k] + minWay[k][j]) { // Если пройти напрямую из i в j "дороже", чем из i в k, а затем из k в j
  185.                             minWay[i][j] = minWay[i][k] + minWay[k][j]; // то записываем в матрицу длин суммму пути из i в k и из k в j
  186.                             children[i][j] = children[i][k]; // а в матрицу детей - узел, в который нужно пойти, чтобы попасть из i в k
  187.                         }
  188.                     }
  189.                 }
  190.             }
  191.         }
  192.  
  193.         /*// Для тестов
  194.  
  195.         // Вывод матрицы длин кратчайших путей для каждой пары узлов
  196.         cout << "Min Way:" << endl;
  197.         for (int i = 1; i <= n; i++) {
  198.             for (int j = 1; j <= n; j++) {
  199.                 cout << minWay[i][j] << " ";
  200.             }
  201.             cout << endl;
  202.         }
  203.         cout << endl;
  204.  
  205.         // Вывод матрицы детей
  206.         cout << "Children:" << endl;
  207.         for (int i = 1; i <= n; i++) {
  208.             for (int j = 1; j <= n; j++) {
  209.                 cout << children[i][j] << " ";
  210.             }
  211.             cout << endl;
  212.         }
  213.         cout << endl;
  214.         */
  215.  
  216.         if (minWay[first][second] != INF) { // Если путь есть
  217.             cout << "Length of the way between " << first << " node and " << second << " node: " << minWay[first][second] << endl; // Вывод длины кратчайшего пути для заданных узлов
  218.  
  219.             // Вывод кратчайшего пути для заданных узлов
  220.             cout << "Way: ";
  221.             int step = first; // Первый шаг - начальный узел
  222.             cout << step; // Выводим начальный узел
  223.             while (step != second) {
  224.                 step = children[step][second]; // Находим следующий шаг по матрице детей
  225.                 cout << "->" << step; // Выводим его
  226.             }
  227.             cout << endl;
  228.         }
  229.         else { // Если пути нет
  230.             cout << "No way between " << first << " node and " << second << " node" << endl; // Выводим, что между заданными узлами нет пути
  231.         }
  232.     }
  233. };
  234.  
  235. int main()
  236. {
  237.     string ans;
  238.     cout << "Hello! Do you want to create graph? (y/n) ";
  239.     cin >> ans;
  240.     if (ans != "y") {
  241.         return 0;
  242.     }
  243.     int nodes;
  244.     cout << "Ok! Enter count of nodes: ";
  245.     cin >> nodes;
  246.     Graph graph(nodes);
  247. TYPE:
  248.     cout << "=================================" << endl;
  249.     cout << "What graph it is?" << endl;
  250.     cout << "1. weighted graph" << endl;
  251.     cout << "2. UNweighted graph" << endl;
  252.     cout << "=================================" << endl;
  253.     cout << "Enter your choice: ";
  254.     int choice1;
  255.     cin >> choice1;
  256.     switch (choice1)
  257.     {
  258.     case 1:
  259.         graph.fillGraphWithWeight();
  260.         break;
  261.     case 2:
  262.         graph.fillGraph();
  263.         break;
  264.     default:
  265.         cout << "Try again" << endl;
  266.         goto TYPE;
  267.     }
  268. MENU:
  269.     cout << "=================================" << endl;
  270.     cout << "What are you want to do?" << endl;
  271.     cout << "1. Enter new edge" << endl;
  272.     cout << "2. Print all simple chains in graph" << endl;
  273.     cout << "3. Find min way between 2 nodes" << endl;
  274.     cout << "4. Print graph as matrix" << endl;
  275.     cout << "5. Print graph as list" << endl;
  276.     cout << "0. Exit" << endl;
  277.     cout << "=================================" << endl;
  278.     cout << "Enter your choice: ";
  279.     int choice2;
  280.     cin >> choice2;
  281.     switch (choice2)
  282.     {
  283.     case 1:
  284.         if (choice1 == 1) {
  285.             graph.fillGraphWithWeight();
  286.         }
  287.         else {
  288.             graph.fillGraph();
  289.         }
  290.         goto MENU;
  291.         break;
  292.     case 2:
  293.         graph.showAllChains();
  294.         goto MENU;
  295.         break;
  296.     case 3:
  297.         int first, second;
  298.         cout << "Enter nodes:" << endl;
  299.         cout << "first: ";
  300.         cin >> first;
  301.         cout << "second: ";
  302.         cin >> second;
  303.         graph.minWayByFloyd(first, second);
  304.         goto MENU;
  305.         break;
  306.     case 4:
  307.         graph.printMatrix();
  308.         goto MENU;
  309.         break;
  310.     case 5:
  311.         graph.printList();
  312.         goto MENU;
  313.         break;
  314.     case 0:
  315.         return 0;
  316.     default:
  317.         cout << "Try again" << endl;
  318.         goto MENU;
  319.     }
  320. }
  321.  
Add Comment
Please, Sign In to add comment