Advertisement
Tvor0zhok

Графы потоки

Dec 4th, 2022
834
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 14.56 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 int INF = 1e9 + 7;
  22.  
  23. /// <summary>
  24. /// Граф
  25. /// </summary>
  26. /// <typeparam name="Vertice"> тип вершин графа </typeparam>
  27. /// <typeparam name="Weight"> тип ребер графа (int по умолчанию) </typeparam>
  28. template <class Vertice, class Weight = 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, Weight>> 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, Weight>>(v, map<Vertice, Weight>()));
  88.         }
  89.  
  90.         fin >> cmd >> _M;
  91.  
  92.         for (int i = 0; i < _M; ++i)
  93.         {
  94.             Vertice u, v; Weight w; fin >> u >> v;
  95.  
  96.             if (!IsWeighted) w = 1;
  97.             else fin >> w;
  98.  
  99.             graph[u].insert(pair<Vertice, Weight>(v, w));
  100.             if (!IsDirected) graph[v].insert(pair<Vertice, Weight>(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, Weight>> 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, Weight>>(v, map<Vertice, Weight>()));
  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, Weight 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; Weight 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; Weight 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. template <class Weight>
  337. struct Edge
  338. {
  339.     Weight f, c; // поток и пропускная способность
  340.  
  341.     Edge() {}
  342.     Edge(Weight c) : f(0), c(c) {};
  343. };
  344.  
  345. template <class Vertice, class Weight>
  346. Weight DFS(map<Vertice, map<Vertice, Edge<Weight>>>& edges, map<Vertice, bool> &used, Vertice u, Vertice t, Weight c, Weight B)
  347. {
  348.     used[u] = true;
  349.  
  350.     if (u == t) return c;
  351.  
  352.     for (auto p : edges[u])
  353.     {
  354.         Vertice v = p.first;
  355.         Edge<Weight> e = p.second;
  356.  
  357.         if (!used[v] && (e.c - e.f) >= B)
  358.         {
  359.             Weight r = DFS(edges, used, v, t, min(c, e.c - e.f), B);
  360.  
  361.             if (r > 0)
  362.             {
  363.                 edges[u][v].f += r; // r (литров) жижи течет по ребру u->v
  364.                 edges[v][u].f -= r; // -r (литров) жижи течет по обратному ребру v->u
  365.  
  366.                 return r;
  367.             }
  368.         }
  369.     }
  370.  
  371.     return 0;
  372. }
  373.  
  374. template <class Vertice, class Weight>
  375. void FordFalkerson(Graph <Vertice, Weight>& g, Vertice s, Vertice t)
  376. {
  377.     map <Vertice, map<Vertice, Weight>> _edges = g.edges();
  378.     map <Vertice, map<Vertice, Edge<Weight>>> edges;
  379.  
  380.     for (auto p1 : _edges)
  381.     {
  382.         Vertice u = p1.first;
  383.         edges[u] = map<Vertice, Edge<Weight>>();
  384.  
  385.         for (auto p2 : _edges[u])
  386.         {
  387.             Vertice v = p2.first;
  388.             Weight c = p2.second;
  389.  
  390.             edges[u][v] = Edge<Weight>(c);
  391.         }
  392.     }
  393.  
  394.     int B = 1ll << 30; // 2^30
  395.  
  396.     for (; B > 0; B /= 2)
  397.     {
  398.         while (true)
  399.         {
  400.             map <Vertice, bool> used;
  401.             for (auto p : edges) used[p.first] = false;
  402.  
  403.             Weight r = DFS(edges, used, s, t, INF, B);
  404.  
  405.             if (r == 0) break;
  406.         }
  407.     }
  408.  
  409.     Weight max_flow = 0;
  410.  
  411.     for (auto p : edges[s])
  412.     {
  413.         Edge<Weight> e = p.second;
  414.         max_flow += e.f;
  415.     }
  416.  
  417.     cout << "Максимальный поток равен: " << max_flow << "\n";
  418.  
  419.     for (auto p : edges)
  420.     {
  421.         Vertice s = p.first;
  422.  
  423.         cout << s << ": ";
  424.  
  425.         for (auto p : edges[s])
  426.         {
  427.             Vertice v = p.first;
  428.             Edge<Weight> e = p.second;
  429.  
  430.             if (e.f > 0) cout << "(" << v << ", " << e.f << ") ";
  431.         }
  432.  
  433.         cout << "\n";
  434.     }
  435. }
  436.  
  437. //////////////////////////////////////////////
  438. //            ConsoleInterface.h            //
  439. //////////////////////////////////////////////
  440.  
  441. #pragma once
  442. #include "Graph.h"
  443. #include <vector>
  444. #include <string>
  445.  
  446. /// <summary>
  447. /// Консольный интерфейс, работающий с одним графом
  448. /// </summary>
  449. /// <typeparam name="Vertice"> тип вершин графа </typeparam>
  450. /// <typeparam name="Weight"> тип ребер графа </typeparam>
  451. template <class Vertice, class Weight = int>
  452. class ConsoleInterface
  453. {
  454.     /// <summary>
  455.     /// Граф
  456.     /// </summary>
  457.     Graph<Vertice, Weight> g;
  458.  
  459.     /// <summary>
  460.     /// Вывод на консоль списка доступных команд
  461.     /// </summary>
  462.     void Hint()
  463.     {
  464.         cout << "+---------------------------------------+\n";
  465.         cout << "|             СПИСОК КОМАНД             |\n";
  466.         cout << "+---------------------------------------+\n";
  467.         cout << "|  1. CREATE GRAPH direction weighting  |\n";
  468.         cout << "|  2. CREATE GRAPH filePath             |\n";
  469.         cout << "|  3. ADD VERTICE v                     |\n";
  470.         cout << "|  4. REMOVE VERTICE v                  |\n";
  471.         cout << "|  5. ADD EDGE u v [w]                  |\n";
  472.         cout << "|  6. REMOVE EDGE u w                   |\n";
  473.         cout << "|  7. CLEAR GRAPH                       |\n";
  474.         cout << "|  8. PRINT GRAPH filePath              |\n";
  475.         cout << "|  9. MAX FLOW s t                      |\n";
  476.         cout << "|  10. GET HINT                         |\n";
  477.         cout << "|  11. EXIT                             |\n";
  478.         cout << "+---------------------------------------+\n";
  479.     }
  480.  
  481. public:
  482.  
  483.     /// <summary>
  484.     /// Конструктор по умолчанию
  485.     /// </summary>
  486.     ConsoleInterface() {};
  487.  
  488.     /// <summary>
  489.     /// Запуск интерфейса
  490.     /// </summary>
  491.     void Start()
  492.     {
  493.         Hint();
  494.  
  495.         while (true)
  496.         {
  497.             cout << ">> ";
  498.  
  499.             string w1; cin >> w1;
  500.  
  501.             if (w1 == "CREATE")
  502.             {
  503.                 string w2, w3; cin >> w2 >> w3;
  504.  
  505.                 if (w3 == "directed" || w3 == "undirected")
  506.                 {
  507.                     string w4; cin >> w4;
  508.                     g = Graph<Vertice, Weight>(w3, w4);
  509.                 }
  510.                 else g = Graph<Vertice, Weight>(w3);
  511.             }
  512.             else if (w1 == "ADD")
  513.             {
  514.                 string w2; cin >> w2;
  515.  
  516.                 if (w2 == "VERTICE")
  517.                 {
  518.                     Vertice w3; cin >> w3;
  519.                     g.addVertice(w3);
  520.                 }
  521.                 else
  522.                 {
  523.                     Vertice w3, w4; Weight w5; cin >> w3 >> w4;
  524.  
  525.                     if (!g.isWeighted()) w5 = 1;
  526.                     else cin >> w5;
  527.  
  528.                     g.addEdge(w3, w4, w5);
  529.                 }
  530.             }
  531.             else if (w1 == "REMOVE")
  532.             {
  533.                 string w2; cin >> w2;
  534.  
  535.                 if (w2 == "VERTICE")
  536.                 {
  537.                     Vertice w3; cin >> w3;
  538.                     g.removeVertice(w3);
  539.                 }
  540.                 else
  541.                 {
  542.                     Vertice w3, w4; cin >> w3 >> w4;
  543.                     g.removeEdge(w3, w4);
  544.                 }
  545.             }
  546.             else if (w1 == "CLEAR")
  547.             {
  548.                 string w2; cin >> w2;
  549.                 g.clear();
  550.             }
  551.             else if (w1 == "PRINT")
  552.             {
  553.                 string w2, w3; cin >> w2 >> w3;
  554.                 g.print(w3);
  555.             }
  556.             else if (w1 == "MAX")
  557.             {
  558.                 string w2; cin >> w2;
  559.                 Vertice w3, w4; cin >> w3 >> w4;
  560.  
  561.                 FordFalkerson(g, w3, w4);
  562.             }
  563.             else if (w1 == "GET")
  564.             {
  565.                 string w2; cin >> w2;
  566.                 Hint();
  567.             }
  568.             else if (w1 == "EXIT")
  569.             {
  570.                 break;
  571.             }
  572.         }
  573.     }
  574. };
  575.  
  576. /////////////////////////////////////
  577. //            Graph.cpp            //
  578. /////////////////////////////////////
  579.  
  580. #include "ConsoleInterface.h"
  581. #include <Windows.h>
  582.  
  583. int main()
  584. {
  585.     SetConsoleCP(1251);
  586.     SetConsoleOutputCP(1251);
  587.  
  588.     ConsoleInterface<int, int> consoleInterface;
  589.     consoleInterface.Start();
  590.  
  591.     return 0;
  592. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement