Advertisement
Tvor0zhok

Минимальный срез. Алгоритм Диница (без масштабирования)

Apr 19th, 2022
841
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 3.42 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. const ll INF = 1e9 + 7;
  14.  
  15. struct Edge // 2-ой вариант представления ребер
  16. {
  17.     int u, v; // u -> v
  18.     ll f, c; // поток и пропускная способность ребра
  19.  
  20.     int rev; // позиция обратного ребра (v -> u) в списке смежности
  21.              // пример обращения: g[e.v][e.rev]
  22.  
  23.     Edge(int u, int v, ll c) : u(u), v(v), f(0), c(c) {}; // f = 0 т.к. изначально жижа не течет
  24. };
  25.  
  26. int n, m;
  27. vector <Edge> g[107];
  28. int d[107], visited[107], first[107];
  29.  
  30. // DFS: АЛГОРИТМ ДИНИЦА (БЕЗ МАСШТАБИРОВАНИЯ)
  31.  
  32. ll DFS(int u, ll c)
  33. {
  34.     visited[u] = 1;
  35.  
  36.     if (u == n) return c;
  37.  
  38.     for (; first[u] < g[u].size(); ++first[u])
  39.     {
  40.         Edge e = g[u][first[u]];
  41.  
  42.         if (!visited[e.v] && (d[e.v] = d[u] + 1) && (e.c - e.f) > 0)
  43.         {
  44.             ll r = DFS(e.v, min(c, e.c - e.f));
  45.  
  46.             if (r > 0)
  47.             {
  48.                 g[u][first[u]].f += r;
  49.                 g[e.v][e.rev].f -= r; // -r даже для неориентированного графа в силу св-в потока
  50.  
  51.                 return r;
  52.             }
  53.         }
  54.     }
  55.  
  56.     return 0;
  57. }
  58.  
  59. // BFS: АЛГОРИТМ ДИНИЦА (БЕЗ МАСШТАБИРОВАНИЯ)
  60.  
  61. bool BFS()
  62. {
  63.     for (int i = 1; i <= n; ++i) d[i] = -1;
  64.    
  65.     queue <int> q;
  66.  
  67.     q.push(1); d[1] = 0;
  68.  
  69.     while (!q.empty())
  70.     {
  71.         int u = q.front(); q.pop();
  72.  
  73.         for (int j = 0; j < g[u].size(); ++j)
  74.         {
  75.             Edge e = g[u][j];
  76.  
  77.             if (d[e.v] == -1 && e.f < e.c)
  78.             {
  79.                 q.push(e.v);
  80.  
  81.                 d[e.v] = d[u] + 1;
  82.             }
  83.         }
  84.     }
  85.  
  86.     return d[n] != -1; // мы достигли вершины t (t = n) или нет?
  87. }
  88.  
  89. int main()
  90. {
  91.     ios_base::sync_with_stdio(0);
  92.     cin.tie(0); cout.tie(0);
  93.  
  94.     cin >> n >> m;
  95.  
  96.     vii edges(m);
  97.  
  98.     for (int i = 0; i < m; ++i)
  99.     {
  100.         // нумерация вершин начинается с 1
  101.  
  102.         int u, v, c; cin >> u >> v >> c;
  103.  
  104.         Edge e = Edge(u, v, c);
  105.         Edge inv_e = Edge(v, u, c); // обратим внимание что для неориентированного графа c != 0
  106.  
  107.         g[u].push_back(e);
  108.         g[v].push_back(inv_e);
  109.  
  110.         g[u][g[u].size() - 1].rev = g[v].size() - 1;
  111.         g[v][g[v].size() - 1].rev = g[u].size() - 1;
  112.  
  113.         edges[i] = { u, v };
  114.     }
  115.  
  116.     // АЛГОРИТМ ДИНИЦА
  117.  
  118.     while (BFS())
  119.     {
  120.         for (int i = 1; i <= n; ++i) first[i] = 0;
  121.  
  122.         while (true)
  123.         {
  124.             for (int i = 1; i <= n; ++i) visited[i] = 0;
  125.  
  126.             ll r = DFS(1, INF);
  127.  
  128.             if (r == 0) break;
  129.         }
  130.     }
  131.  
  132.     for (int i = 1; i <= n; ++i) visited[i] = 0;
  133.  
  134.     // поиск минимального разреза
  135.  
  136.     queue <int> q;
  137.  
  138.     q.push(1); visited[1] = 1;
  139.  
  140.     while (!q.empty())
  141.     {
  142.         int u = q.front(); q.pop();
  143.  
  144.         for (int j = 0; j < g[u].size(); ++j)
  145.         {
  146.             Edge e = g[u][j];
  147.  
  148.             if (!visited[e.v] && e.f < e.c)
  149.             {
  150.                 q.push(e.v);
  151.  
  152.                 visited[e.v] = 1;
  153.             }
  154.         }
  155.     }
  156.  
  157.     ll maxFlow = 0;
  158.  
  159.     for (int j = 0; j < g[1].size(); ++j)
  160.         maxFlow += g[1][j].f;
  161.  
  162.     vi pos; // для ответа
  163.  
  164.  
  165.     for (int i = 0; i < m; ++i)
  166.     {
  167.         int u = edges[i].first, v = edges[i].second;
  168.  
  169.         if (visited[u] != visited[v]) pos.push_back(i + 1);
  170.     }
  171.  
  172.     cout << pos.size() << " " << maxFlow << "\n";
  173.  
  174.     for (int j = 0; j < pos.size(); ++j)
  175.         cout << pos[j] << " ";
  176.  
  177.     return 0;
  178. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement