Advertisement
Tvor0zhok

Максимальный поток. Алгоритм Форда-Фалкерсона

Apr 19th, 2022 (edited)
996
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 2.65 KB | None | 0 0
  1. #include <algorithm>
  2. #include <iostream>
  3. #include <utility>
  4. #include <vector>
  5. #include <queue>
  6. using namespace std;
  7.  
  8. typedef long long ll;
  9. typedef pair <int, int> ii;
  10. typedef vector <int> vi;
  11. typedef vector <ii> vii;
  12.  
  13. struct Edge // 2-ой вариант представления ребер
  14. {
  15.     int u, v; // u -> v
  16.     ll f, c; // поток и пропускная способность ребра
  17.  
  18.     int rev; // позиция обратного ребра (v -> u) в списке смежности
  19.              // пример обращения: g[e.v][e.rev]
  20.  
  21.     Edge(int u, int v, ll c) : u(u), v(v), f(0), c(c) {}; // f = 0 т.к. изначально жижа не течет
  22. };
  23.  
  24. ll B = 1ll << 30; // 2^30
  25. const ll INF = 1e9 + 7;
  26.  
  27. int n, m;
  28. vector <Edge> g[507];
  29. bool visited[507];
  30.  
  31. // DFS: АЛГОРИТМ ФОРДА-ФАЛКЕРСОНА (С МАШТАБИРОВАНИЕМ)
  32.  
  33. ll DFS(int u, ll c)
  34. {
  35.     visited[u] = true;
  36.  
  37.     if (u == n)
  38.     {
  39.         return c;
  40.     }
  41.  
  42.     for (int j = 0; j < g[u].size(); ++j)
  43.     {
  44.         Edge e = g[u][j];
  45.  
  46.         if (!visited[e.v] && (e.c - e.f) >= B)
  47.         {          
  48.             ll r = DFS(e.v, min(c, e.c - e.f));
  49.  
  50.             if (r > 0)
  51.             {
  52.                 g[u][j].f += r; // r (литров) жижи течет по ребру u->v
  53.                 g[e.v][e.rev].f -= r; // -r (литров) жижи течет по обратному ребру v->u
  54.  
  55.                 return r;
  56.             }
  57.         }
  58.     }
  59.  
  60.     return 0;
  61. }
  62.  
  63. int main()
  64. {
  65.     ios_base::sync_with_stdio(0);
  66.     cin.tie(0); cout.tie(0);
  67.  
  68.     cin >> n >> m;
  69.  
  70.     vii edges(m); // для ответа (не суть алгоритма)
  71.  
  72.     for (int i = 0; i < m; ++i)
  73.     {
  74.         // нумерация ребер с 1
  75.  
  76.         int u, v, c; cin >> u >> v >> c;
  77.  
  78.         Edge e = Edge(u, v, c);
  79.         Edge inv_e = Edge(v, u, 0);  // ребро и обратное ребро
  80.  
  81.         g[u].push_back(e);
  82.         g[v].push_back(inv_e);
  83.  
  84.         g[u][g[u].size() - 1].rev = g[v].size() - 1;
  85.         g[v][g[v].size() - 1].rev = g[u].size() - 1;
  86.  
  87.         edges[i] = { u, g[u].size() - 1 };
  88.     }
  89.  
  90.     // АЛГОРИТМ ФОРДА-ФАЛКЕРСОНА (С МАШТАБИРОВАНИЕМ)
  91.  
  92.     for (; B > 0; B /= 2)
  93.     {
  94.         while (true)
  95.         {
  96.             // НУМЕРАЦИЯ ВЕРШИН ОТ 1 ДО n
  97.  
  98.             for (int i = 1; i <= n; ++i) visited[i] = false;
  99.            
  100.             ll r = DFS(1, INF);
  101.  
  102.             if (r == 0) break;
  103.         }
  104.  
  105.     }
  106.  
  107.     // Подсчет максимального потока: сумма всех потоков из вершины s (1 = s в данной задаче)
  108.  
  109.     ll ans = 0;
  110.  
  111.     for (int j = 0; j < g[1].size(); ++j)
  112.         ans += g[1][j].f;
  113.  
  114.     cout << ans << "\n";
  115.    
  116.     for (int i = 0; i < m; ++i)
  117.     {
  118.         int u = edges[i].first, pos = edges[i].second;
  119.  
  120.         cout << g[u][pos].f << "\n";
  121.     }
  122.  
  123.     return 0;
  124. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement