Advertisement
Tvor0zhok

Графы веса

Nov 6th, 2022
1,148
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 22.75 KB | None | 0 0
  1. ////////////////////////////////////////////////////////////////////////////////////////////////////////
  2. // GOOGLE DRIVE: https://drive.google.com/drive/folders/1eNXlQ50LanvYKPj_qr-Qr2qJmPa2o_Ze?usp=sharing //
  3. ////////////////////////////////////////////////////////////////////////////////////////////////////////
  4.  
  5. ///////////////////////////////////
  6. //            Graph.h            //
  7. ///////////////////////////////////
  8.  
  9. #pragma once
  10. #include <algorithm>
  11. #include <iostream>
  12. #include <iomanip>
  13. #include <fstream>
  14. #include <utility>
  15. #include <vector>
  16. #include <queue>
  17. #include <map>
  18. #include <set>
  19. using namespace std;
  20.  
  21. const double INF = 1e9 + 7;
  22.  
  23. /// <summary>
  24. /// Граф
  25. /// </summary>
  26. /// <typeparam name="Vertice"> тип вершин графа </typeparam>
  27. /// <typeparam name="Edge"> тип ребер графа (int по умолчанию) </typeparam>
  28. template <class Vertice, class Edge = int>
  29. class Graph
  30. {
  31.     /// <summary>
  32.     /// Количество вершин и ребер в графе
  33.     /// </summary>
  34.     int _N = 0, _M = 0;
  35.  
  36.     /// <summary>
  37.     /// Критерий ориентированности и взвешенности графа
  38.     /// </summary>
  39.     bool IsDirected = false, IsWeighted = false;
  40.  
  41.     /// <summary>
  42.     /// Список смежности графа
  43.     /// </summary>
  44.     map <Vertice, map<Vertice, Edge>> graph;
  45.  
  46. public:
  47.  
  48.     /// <summary>
  49.     /// Конструктор по умолчанию
  50.     /// </summary>
  51.     Graph() {};
  52.  
  53.     /// <summary>
  54.     /// Конструктор, создающий пустой граф, определяющий
  55.     /// ориентированность и взвешенность графа
  56.     /// </summary>
  57.     /// <param name="direction"> критерий ориентированности </param>
  58.     /// <param name="weighting"> критерий взвешенности </param>
  59.     Graph(string direction, string weighting)
  60.     {
  61.         if (direction == "directed") IsDirected = true;
  62.         if (weighting == "weighted") IsWeighted = true;
  63.     }
  64.  
  65.     /// <summary>
  66.     /// Конструктор, считывающий информацию из файла
  67.     /// или из консоли (stdin)
  68.     /// </summary>
  69.     /// <param name="filePath"> путь к файлу или ключевое слово stdin </param>
  70.     Graph(string filePath)
  71.     {
  72.         ifstream fin;
  73.  
  74.         if (filePath == "stdin") fin = ifstream(stdin);
  75.         else fin = ifstream(filePath);
  76.  
  77.         string cmd, direction, weighting;
  78.         fin >> cmd >> direction >> weighting;
  79.  
  80.         *this = Graph(direction, weighting);
  81.  
  82.         fin >> cmd >> _N;
  83.  
  84.         for (int i = 0; i < _N; ++i)
  85.         {
  86.             Vertice v; fin >> v;
  87.             graph.insert(pair<Vertice, map<Vertice, Edge>>(v, map<Vertice, Edge>()));
  88.         }
  89.  
  90.         fin >> cmd >> _M;
  91.  
  92.         for (int i = 0; i < _M; ++i)
  93.         {
  94.             Vertice u, v; Edge w; fin >> u >> v;
  95.  
  96.             if (!IsWeighted) w = 1;
  97.             else fin >> w;
  98.  
  99.             graph[u].insert(pair<Vertice, Edge>(v, w));
  100.             if (!IsDirected) graph[v].insert(pair<Vertice, Edge>(u, w));
  101.         }
  102.  
  103.         if (filePath != "stdin") fin.close();
  104.     }
  105.  
  106.     /// <summary>
  107.     /// Количество вершин графа
  108.     /// </summary>
  109.     /// <returns> количество вершин графа </returns>
  110.     int n() { return _N; }
  111.  
  112.     /// <summary>
  113.     /// Количество ребер графа
  114.     /// </summary>
  115.     /// <returns> количество ребер графа </returns>
  116.     int m() { return _M; }
  117.  
  118.     /// <summary>
  119.     /// Метод, выдающий информацию об
  120.     /// ориентированности графа
  121.     /// </summary>
  122.     /// <returns> true, если граф ориентированный, иначе - false </returns>
  123.     bool isDirected() { return IsDirected; }
  124.  
  125.     /// <summary>
  126.     /// Метод, выдающий информацию о
  127.     /// взвешенности графа
  128.     /// </summary>
  129.     /// <returns> true, если граф взвешенный, иначе - false </returns>
  130.     bool isWeighted() { return IsWeighted; }
  131.  
  132.     /// <summary>
  133.     /// Метод, возращающий список смежности графа
  134.     /// </summary>
  135.     /// <returns> список смежности графа </returns>
  136.     map<Vertice, map<Vertice, Edge>> edges() { return graph; }
  137.  
  138.     /// <summary>
  139.     /// Добавление вершины в граф
  140.     /// </summary>
  141.     /// <param name="v"> добавляемая в граф вершина </param>
  142.     void addVertice(Vertice v)
  143.     {
  144.         try
  145.         {
  146.             if (graph.find(v) != graph.end()) throw "Добавление вершины: заданная вершина уже есть в графе";
  147.             else
  148.             {
  149.                 ++_N;
  150.                 graph.insert(pair<Vertice, map<Vertice, Edge>>(v, map<Vertice, Edge>()));
  151.             }
  152.         }
  153.         catch (const char* msg)
  154.         {
  155.             cout << msg << "\n";
  156.         }
  157.     }
  158.  
  159.     /// <summary>
  160.     /// Удаление вершины из графа
  161.     /// </summary>
  162.     /// <param name="v"> удаляемая из графа вершина </param>
  163.     void removeVertice(Vertice v)
  164.     {
  165.         try
  166.         {
  167.             if (graph.find(v) == graph.end()) throw "Удаление вершины: в графе отсутствует заданная вершина";
  168.             else
  169.             {
  170.                 --_N; _M -= graph[v].size();
  171.  
  172.                 graph.erase(v);
  173.  
  174.                 for (auto p : graph)
  175.                     if (graph[p.first].find(v) != graph[p.first].end())
  176.                     {
  177.                         if (IsDirected) --_M;
  178.                         graph[p.first].erase(v);
  179.                     }
  180.             }
  181.         }
  182.         catch (const char* msg)
  183.         {
  184.             cout << msg << "\n";
  185.         }
  186.     }
  187.  
  188.     /// <summary>
  189.     /// Добавление ребра в граф
  190.     /// </summary>
  191.     /// <param name="u"> первая вершина ребра </param>
  192.     /// <param name="v"> вторая вершина ребра </param>
  193.     /// <param name="w"> вес ребра (для невзвешенных графов w = 1) </param>
  194.     void addEdge(Vertice u, Vertice v, Edge w)
  195.     {
  196.         try
  197.         {
  198.             if (graph.find(u) == graph.end() || graph.find(v) == graph.end()) throw "Добавление ребра: в графе отсутствует(ют) заданная(ые) вершина(ы)";
  199.             else if (!IsDirected && u == v) throw "Добавление ребра: невозможно добавить петлю в неориентированный граф";
  200.             else if (graph[u].find(v) != graph[u].end()) throw "Добавление ребра: заданное ребро уже есть в графе";
  201.             else
  202.             {
  203.                 ++_M;
  204.                 graph[u][v] = w;
  205.                 if (!IsDirected) graph[v][u] = w;
  206.             }
  207.         }
  208.         catch (const char* msg)
  209.         {
  210.             cout << msg << "\n";
  211.         }
  212.     }
  213.  
  214.     /// <summary>
  215.     /// Удаление ребра из графа
  216.     /// </summary>
  217.     /// <param name="u"> первая вершина ребра </param>
  218.     /// <param name="v"> вторая вершина ребра </param>
  219.     void removeEdge(Vertice u, Vertice v)
  220.     {
  221.         try
  222.         {
  223.             if (graph.find(u) == graph.end() || graph.find(v) == graph.end()) throw "Удаление ребра: в графе отсутствует(ют) заданная(ые) вершина(ы)";
  224.             else
  225.             {
  226.                 if (graph[u].find(v) == graph[u].end()) throw "Удаление ребра: в графе отсутствует заданное ребро";
  227.                 else
  228.                 {
  229.                     --_M;
  230.                     graph[u].erase(v);
  231.                     if (!IsDirected) graph[v].erase(u);
  232.                 }
  233.             }
  234.         }
  235.         catch (const char* msg)
  236.         {
  237.             cout << msg << "\n";
  238.         }
  239.     }
  240.  
  241.     /// <summary>
  242.     /// Очищение графа (ориентированность
  243.     /// и взвешенность остаются прежними)
  244.     /// </summary>
  245.     void clear()
  246.     {
  247.         _N = 0; _M = 0;
  248.         graph.clear();
  249.     }
  250.  
  251.     /// <summary>
  252.     /// Вывод информации о графе в файл или
  253.     /// на консоль (stdout)
  254.     /// </summary>
  255.     /// <param name="filePath"> путь к файлу или ключевое слово stdout </param>
  256.     void print(string filePath)
  257.     {
  258.         ofstream fout;
  259.  
  260.         if (filePath == "stdout") fout = ofstream(stdout);
  261.         else fout = ofstream(filePath);
  262.  
  263.         if (filePath != "stdout")
  264.         {
  265.             fout << "GRAPH ";
  266.  
  267.             if (IsDirected) fout << "directed ";
  268.             else fout << "undirected ";
  269.  
  270.             if (IsWeighted) fout << "weighted\n";
  271.             else fout << "unweighted\n";
  272.  
  273.             fout << "VERTICES: " << _N << "\n";
  274.  
  275.             for (auto p : graph)
  276.                 fout << p.first << "\n";
  277.  
  278.             fout << "EDGES: " << _M << "\n";
  279.  
  280.             for (auto p1 : graph)
  281.             {
  282.                 Vertice u = p1.first;
  283.  
  284.                 for (auto p2 : p1.second)
  285.                 {
  286.                     Vertice v = p2.first; Edge w = p2.second;
  287.  
  288.                     if (IsDirected || u < v)
  289.                     {
  290.                         fout << u << " " << v << " ";
  291.                         if (IsWeighted) fout << w;
  292.                         fout << "\n";
  293.                     }
  294.                 }
  295.             }
  296.  
  297.             fout.close();
  298.         }
  299.         else
  300.         {
  301.             fout << "GRAPH ";
  302.  
  303.             if (IsDirected) fout << "directed ";
  304.             else fout << "undirected ";
  305.  
  306.             if (IsWeighted) fout << "weighted\n";
  307.             else fout << "unweighted\n";
  308.  
  309.             fout << "VERTICES: " << _N << "\n";
  310.  
  311.             for (auto p : graph)
  312.                 fout << p.first << "\n";
  313.  
  314.             fout << "EDGES: " << _M << "\n";
  315.  
  316.             for (auto p1 : graph)
  317.             {
  318.                 Vertice u = p1.first;
  319.  
  320.                 fout << u << ": ";
  321.  
  322.                 for (auto p2 : p1.second)
  323.                 {
  324.                     Vertice v = p2.first; Edge w = p2.second;
  325.  
  326.                     if (!IsWeighted) fout << v << " ";
  327.                     else fout << "(" << v << ", " << w << ") ";
  328.                 }
  329.  
  330.                 fout << "\n";
  331.             }
  332.         }
  333.     }
  334. };
  335.  
  336. /// <summary>
  337. /// Алгоритм Дейстры поиска кратчайшего пути
  338. /// между двумя заданными вершинами
  339. /// </summary>
  340. /// <typeparam name="Vertice"> тип вершин графа </typeparam>
  341. /// <typeparam name="Edge"> тип ребер графа </typeparam>
  342. /// <param name="edges"> список смежности графа </param>
  343. /// <param name="s"> начало пути </param>
  344. /// <param name="t"> конец пути </param>
  345. /// <param name="parents"> список предков вершин графа </param>
  346. /// <returns> расстояние между вершинами s и t </returns>
  347. template <class Vertice, class Edge>
  348. Edge Dijkstra(map<Vertice, map<Vertice, Edge>> &edges, Vertice s, Vertice t, map<Vertice, set<Vertice>> &parents)
  349. {
  350.     map<Vertice, Edge> dist;
  351.  
  352.     for (auto p : edges)
  353.     {
  354.         Vertice u = p.first;
  355.         dist[u] = INF;
  356.     }
  357.  
  358.     priority_queue <pair<Edge, Vertice>, vector<pair<Edge, Vertice>>, greater<pair<Edge, Vertice>>> pq;
  359.  
  360.     dist[s] = 0;
  361.     pq.push({ dist[s], s });
  362.  
  363.     while (!pq.empty())
  364.     {
  365.         Vertice u = pq.top().second; Edge d = pq.top().first; pq.pop();
  366.  
  367.         if (d > dist[u]) continue;
  368.  
  369.         for (auto p : edges[u])
  370.         {
  371.             Vertice v = p.first; Edge w = p.second;
  372.  
  373.             if (d + w <= dist[v])
  374.             {
  375.                 if (d + w < dist[v])
  376.                 {
  377.                     parents[v].clear();
  378.                     dist[v] = d + w;
  379.                     pq.push({ dist[v], v });
  380.                 }
  381.  
  382.                 parents[v].insert(u);
  383.             }
  384.         }
  385.     }
  386.  
  387.     return dist[t];
  388. }
  389.  
  390. /// <summary>
  391. /// Восстановление путей по предкам
  392. /// </summary>
  393. /// <typeparam name="Vertice"> тип вершин графа </typeparam>
  394. /// <typeparam name="Edge"> тип ребер графа </typeparam>
  395. /// <param name="edges"> список смежности графа </param>
  396. /// <param name="parents"> список предков вершин графа </param>
  397. /// <param name="s"> начало пути </param>
  398. /// <param name="cur"> текущая вершина пути </param>
  399. /// <param name="cnt"> порядковый номер пути </param>
  400. /// <param name="path"> история пути </param>
  401. template <class Vertice, class Edge>
  402. void FindPaths(map<Vertice, map<Vertice, Edge>> &edges, map<Vertice, set<Vertice>>& parents, Vertice s, Vertice cur, int& cnt, int k, vector<Vertice> &path)
  403. {
  404.     if (cnt == k) return;
  405.    
  406.     path.push_back(cur);
  407.  
  408.     if (cur == s)
  409.     {
  410.         cout << ++cnt << ": ";
  411.  
  412.         for (int i = path.size() - 1; i > 0; --i)
  413.         {
  414.             Vertice u = path[i], v = path[i - 1]; Edge w = edges[u][v];
  415.  
  416.             cout << u << " --(" << w << ")--> ";
  417.         }
  418.  
  419.         cout << path[0] << "\n";
  420.     }
  421.     else
  422.     {
  423.         for (auto p : parents[cur])
  424.             FindPaths<Vertice, Edge>(edges, parents, s, p, cnt, k, path);
  425.     }
  426.  
  427.     path.pop_back();
  428. }
  429.  
  430. /// <summary>
  431. /// Задание IV a: поиск всех кратчайших путей
  432. /// между заданными вершинами s и t
  433. /// </summary>
  434. /// <typeparam name="Vertice"> тип вершин графа </typeparam>
  435. /// <typeparam name="Edge"> тип ребер графа </typeparam>
  436. /// <param name="g"> граф </param>
  437. /// <param name="s"> начальная вершина </param>
  438. /// <param name="t"> конечная вершина </param>
  439. template <class Vertice, class Edge>
  440. void AllShortestPaths(Graph<Vertice, Edge>& g, Vertice s, Vertice t)
  441. {
  442.     map<Vertice, map<Vertice, Edge>> edges = g.edges();
  443.     map<Vertice, set<Vertice>> parents;
  444.  
  445.     try
  446.     {
  447.         if (edges.find(s) == edges.end()) throw "Задание IV a: вершины s нет в графе";
  448.         else if (edges.find(t) == edges.end()) throw "Задание IV a: вершины t нет в графе";
  449.         else
  450.         {
  451.             Edge length = Dijkstra(edges, s, t, parents);
  452.  
  453.             if (parents[t].size() == 0) cout << "Вершины s = " << s << " и t = " << t << " находятся в разных компонентах связности\n";
  454.             else
  455.             {
  456.                 cout << "Всевозможные пути (длины " << length << ")\n";
  457.  
  458.                 int cnt = 0;
  459.                 vector<Vertice> path;
  460.                 FindPaths<Vertice, Edge>(edges, parents, s, t, cnt, INF, path);
  461.  
  462.                 cout << "Итого: " << cnt << " различных кратчайших путей\n";
  463.             }
  464.         }
  465.     }
  466.     catch (const char* msg)
  467.     {
  468.         cout << msg << "\n";
  469.     }
  470. }
  471.  
  472. /// <summary>
  473. /// Алгоритм Беллмана-Форда поиска кратчайшего пути
  474. /// между двумя заданными вершинами
  475. /// </summary>
  476. /// <typeparam name="Vertice"> тип вершин графа </typeparam>
  477. /// <typeparam name="Edge"> тип ребер графа </typeparam>
  478. /// <param name="edges"> список смежности графа </param>
  479. /// <param name="s"> начальная вершина </param>
  480. /// <param name="t"> конечная вершина </param>
  481. /// <param name="parents"> список предков вершин графа </param>
  482. /// <returns> расстояние между вершинами s и t </returns>
  483. template <class Vertice, class Edge>
  484. Edge Bellman(map<Vertice, map<Vertice, Edge>>& edges, Vertice s, Vertice t, map<Vertice, set<Vertice>> &parents)
  485. {
  486.     map<Vertice, Edge> dist;
  487.  
  488.     for (auto p : edges)
  489.     {
  490.         Vertice u = p.first;
  491.         dist[u] = INF;
  492.     }
  493.  
  494.     dist[s] = 0;
  495.  
  496.     for (int i = 0; i < edges.size() - 1; ++i)
  497.     {
  498.         bool flag = false;
  499.  
  500.         for (auto p1 : edges)
  501.         {
  502.             Vertice u = p1.first;
  503.  
  504.             if (dist[u] == INF) continue;
  505.  
  506.             for (auto p2 : edges[u])
  507.             {
  508.                 Vertice v = p2.first; Edge w = p2.second;
  509.  
  510.                 if (dist[v] >= dist[u] + w)
  511.                 {
  512.                     if (dist[v] > dist[u] + w)
  513.                     {
  514.                         parents[v].clear();
  515.                         dist[v] = dist[u] + w;
  516.                         flag = true;
  517.                     }
  518.  
  519.                     parents[v].insert(u);
  520.                 }
  521.             }
  522.         }
  523.  
  524.         if (!flag) break;
  525.     }
  526.  
  527.     return dist[t];
  528. }
  529.  
  530. /// <summary>
  531. /// Задание IV b: поиск k кратчайших путей
  532. /// между заданными вершинами s и t
  533. /// </summary>
  534. /// <typeparam name="Vertice"> тип вершин графа </typeparam>
  535. /// <typeparam name="Edge"> тип ребер графа </typeparam>
  536. /// <param name="g"> граф </param>
  537. /// <param name="s"> начальная вершина </param>
  538. /// <param name="t"> конечная вершина </param>
  539. /// <param name="k"> количество кратчайших путей </param>
  540. template <class Vertice, class Edge>
  541. void KShortestPaths(Graph<Vertice, Edge>& g, Vertice s, Vertice t, int k)
  542. {
  543.     map<Vertice, map<Vertice, Edge>> edges = g.edges();
  544.     map<Vertice, set<Vertice>> parents;
  545.  
  546.     try
  547.     {
  548.         if (edges.find(s) == edges.end()) throw "Задание IV b: вершины s нет в графе";
  549.         else if (edges.find(t) == edges.end()) throw "Задание IV b: вершины t нет в графе";
  550.         else if (k < 0) throw "Задание IV b: значение k не может быть отрицательным";
  551.         else
  552.         {
  553.             Edge length = Bellman(edges, s, t, parents);
  554.  
  555.             if (parents[t].size() == 0) cout << "Вершины s = " << s << " и t = " << t << " находятся в разных компонентах связности\n";
  556.             else
  557.             {
  558.                 cout << "Всевозможные пути (длины " << length << ")\n";
  559.  
  560.                 int cnt = 0;
  561.                 vector<Vertice> path;
  562.                 FindPaths<Vertice, Edge>(edges, parents, s, t, cnt, k, path);
  563.  
  564.                 if (cnt < k) cout << "В графе не нашлось k = " << k << " кратчайших путей (всего их " << cnt << ")\n";
  565.                 else cout << "В графе нашлось k = " << k << " кратчайших путей (всего их " << cnt << ")\n";
  566.             }
  567.         }
  568.     }
  569.     catch (const char* msg)
  570.     {
  571.         cout << msg << "\n";
  572.     }
  573. }
  574.  
  575. /// <summary>
  576. /// Алгоритм Флойда поиска кратчайших путей
  577. /// между всеми парами вершин
  578. /// </summary>
  579. /// <typeparam name="Vertice"> тип вершин графа </typeparam>
  580. /// <typeparam name="Edge"> тип ребер графа </typeparam>
  581. /// <param name="mat"> матрица кратчайших расстояний </param>
  582. /// <param name="vertices"> вершины графа </param>
  583. template <class Vertice, class Edge>
  584. void Floyd(map<Vertice, map<Vertice, Edge>>& mat, vector<Vertice>& vertices)
  585. {
  586.     for (auto k : vertices)
  587.     {
  588.         map<Vertice, map<Vertice, Edge>> res = mat;
  589.  
  590.         for (auto u : vertices)
  591.             for (auto v : vertices)
  592.                 if (mat[u][k] != INF && mat[k][v] != INF)
  593.                     res[u][v] = min(mat[u][v], mat[u][k] + mat[k][v]);
  594.  
  595.         mat = res;
  596.     }
  597. }
  598.  
  599. /// <summary>
  600. /// Задание IV c: поиск всех пар вершин, длина
  601. /// пути между которыми может быть сколь угодно малой
  602. /// </summary>
  603. /// <typeparam name="Vertice"> тип вершин графа </typeparam>
  604. /// <typeparam name="Edge"> тип ребер графа </typeparam>
  605. /// <param name="g"> граф </param>
  606. template <class Vertice, class Edge>
  607. void AllPairs(Graph<Vertice, Edge>& g)
  608. {
  609.     vector<Vertice> vertices;
  610.     map<Vertice, map<Vertice, Edge>> mat;
  611.     map <Vertice, map<Vertice, Vertice>> ans;
  612.     map <Vertice, map<Vertice, Edge>> edges = g.edges();
  613.  
  614.     for (auto p : edges)
  615.     {
  616.         Vertice v = p.first;
  617.  
  618.         vertices.push_back(v);
  619.         mat[v] = map<Vertice, Edge>();
  620.         ans[v] = map<Vertice, Vertice>();
  621.     }
  622.  
  623.     for (auto u : vertices)
  624.         for (auto v : vertices)
  625.             mat[u][v] = (u == v || edges[u].count(v) == 0) ? INF : edges[u][v];
  626.  
  627.     Floyd(mat, vertices);
  628.  
  629.     cout << "Матрица расстояний:\n";
  630.  
  631.     for (auto u : vertices)
  632.     {
  633.         cout << u << ": ";
  634.  
  635.         for (auto v : vertices)
  636.         {
  637.             cout << "(" << v << ", ";
  638.  
  639.             if (mat[u][v] == INF) cout << "INF";
  640.             else cout << mat[u][v];
  641.  
  642.             cout << ") ";
  643.         }
  644.  
  645.         cout << "\n";
  646.     }
  647.  
  648.     cout << "\n";
  649.  
  650.     vector <Vertice> in_cycle;
  651.    
  652.     for (auto v : vertices)
  653.         if (mat[v][v] < 0) in_cycle.push_back(v);
  654.  
  655.     for (auto u : vertices)
  656.         for (auto v : vertices)
  657.             for (auto t : in_cycle)
  658.                 if (mat[u][t] != INF && mat[t][v] != INF) ans[u][v] = t;
  659.  
  660.     for (auto u : vertices)
  661.     {
  662.         cout << u << ": ";
  663.  
  664.         for (auto p : ans[u])
  665.         {
  666.             Vertice v = p.first, t = p.second;
  667.             cout << "(" << t << ", " << v << ") ";
  668.         }
  669.  
  670.         cout << "\n";
  671.     }
  672. }
  673.  
  674. //////////////////////////////////////////////
  675. //            ConsoleInterface.h            //
  676. //////////////////////////////////////////////
  677.  
  678. #pragma once
  679. #include "Graph.h"
  680. #include <vector>
  681. #include <string>
  682.  
  683. /// <summary>
  684. /// Консольный интерфейс, работающий с одним графом
  685. /// </summary>
  686. /// <typeparam name="Vertice"> тип вершин графа </typeparam>
  687. /// <typeparam name="Edge"> тип ребер графа </typeparam>
  688. template <class Vertice, class Edge = int>
  689. class ConsoleInterface
  690. {
  691.     /// <summary>
  692.     /// Граф
  693.     /// </summary>
  694.     Graph<Vertice, Edge> g;
  695.  
  696.     /// <summary>
  697.     /// Вывод на консоль списка доступных команд
  698.     /// </summary>
  699.     void Hint()
  700.     {
  701.         cout << "+---------------------------------------+\n";
  702.         cout << "|             СПИСОК КОМАНД             |\n";
  703.         cout << "+---------------------------------------+\n";
  704.         cout << "|  1. CREATE GRAPH direction weighting  |\n";
  705.         cout << "|  2. CREATE GRAPH filePath             |\n";
  706.         cout << "|  3. ADD VERTICE v                     |\n";
  707.         cout << "|  4. REMOVE VERTICE v                  |\n";
  708.         cout << "|  5. ADD EDGE u v [w]                  |\n";
  709.         cout << "|  6. REMOVE EDGE u w                   |\n";
  710.         cout << "|  7. CLEAR GRAPH                       |\n";
  711.         cout << "|  8. PRINT GRAPH filePath              |\n";
  712.         cout << "|  9. TASK Kruskal                      |\n";
  713.         cout << "|  10. TASK Prim                        |\n";
  714.         cout << "|  11. GET HINT                         |\n";
  715.         cout << "|  12. EXIT                             |\n";
  716.         cout << "+---------------------------------------+\n";
  717.     }
  718.  
  719. public:
  720.  
  721.     /// <summary>
  722.     /// Конструктор по умолчанию
  723.     /// </summary>
  724.     ConsoleInterface() {};
  725.  
  726.     /// <summary>
  727.     /// Запуск интерфейса
  728.     /// </summary>
  729.     void Start()
  730.     {
  731.         Hint();
  732.  
  733.         while (true)
  734.         {
  735.             cout << ">> ";
  736.  
  737.             string w1; cin >> w1;
  738.  
  739.             if (w1 == "CREATE")
  740.             {
  741.                 string w2, w3; cin >> w2 >> w3;
  742.  
  743.                 if (w3 == "directed" || w3 == "undirected")
  744.                 {
  745.                     string w4; cin >> w4;
  746.                     g = Graph<Vertice, Edge>(w3, w4);
  747.                 }
  748.                 else g = Graph<Vertice, Edge>(w3);
  749.             }
  750.             else if (w1 == "ADD")
  751.             {
  752.                 string w2; cin >> w2;
  753.  
  754.                 if (w2 == "VERTICE")
  755.                 {
  756.                     Vertice w3; cin >> w3;
  757.                     g.addVertice(w3);
  758.                 }
  759.                 else
  760.                 {
  761.                     Vertice w3, w4; Edge w5; cin >> w3 >> w4;
  762.  
  763.                     if (!g.isWeighted()) w5 = 1;
  764.                     else cin >> w5;
  765.  
  766.                     g.addEdge(w3, w4, w5);
  767.                 }
  768.             }
  769.             else if (w1 == "REMOVE")
  770.             {
  771.                 string w2; cin >> w2;
  772.  
  773.                 if (w2 == "VERTICE")
  774.                 {
  775.                     Vertice w3; cin >> w3;
  776.                     g.removeVertice(w3);
  777.                 }
  778.                 else
  779.                 {
  780.                     Vertice w3, w4; cin >> w3 >> w4;
  781.                     g.removeEdge(w3, w4);
  782.                 }
  783.             }
  784.             else if (w1 == "CLEAR")
  785.             {
  786.                 string w2; cin >> w2;
  787.                 g.clear();
  788.             }
  789.             else if (w1 == "PRINT")
  790.             {
  791.                 string w2, w3; cin >> w2 >> w3;
  792.                 g.print(w3);
  793.             }
  794.             else if (w1 == "TASK")
  795.             {
  796.                 string w2; cin >> w2;
  797.  
  798.                 if (w2 == "Kruskal") MST_Kruskal(g);
  799.                 else if (w2 == "Prim") MST_Prim(g);
  800.             }
  801.             else if (w1 == "GET")
  802.             {
  803.                 string w2; cin >> w2;
  804.                 Hint();
  805.             }
  806.             else if (w1 == "EXIT")
  807.             {
  808.                 break;
  809.             }
  810.         }
  811.     }
  812. };
  813.  
  814. /////////////////////////////////////
  815. //            Graph.cpp            //
  816. /////////////////////////////////////
  817.  
  818. #include "ConsoleInterface.h"
  819. #include <Windows.h>
  820.  
  821. int main()
  822. {
  823.     SetConsoleCP(1251);
  824.     SetConsoleOutputCP(1251);
  825.  
  826.     ConsoleInterface<string, int> consoleInterface;
  827.     consoleInterface.Start();
  828.  
  829.     return 0;
  830. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement