Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <algorithm>
- #include <iostream>
- #include <utility>
- #include <vector>
- #include <queue>
- using namespace std;
- typedef long long ll;
- typedef pair <int, int> ii;
- typedef vector <int> vi;
- typedef vector <ii> vii;
- struct Edge // 2-ой вариант представления ребер
- {
- int u, v; // u -> v
- ll f, c; // поток и пропускная способность ребра
- int rev; // позиция обратного ребра (v -> u) в списке смежности
- // пример обращения: g[e.v][e.rev]
- Edge(int u, int v, ll c) : u(u), v(v), f(0), c(c) {}; // f = 0 т.к. изначально жижа не течет
- };
- ll B = 1ll << 30; // 2^30
- const ll INF = 1e9 + 7;
- int n, m;
- vector <Edge> g[507];
- bool visited[507];
- // DFS: АЛГОРИТМ ФОРДА-ФАЛКЕРСОНА (С МАШТАБИРОВАНИЕМ)
- ll DFS(int u, ll c)
- {
- visited[u] = true;
- if (u == n)
- {
- return c;
- }
- for (int j = 0; j < g[u].size(); ++j)
- {
- Edge e = g[u][j];
- if (!visited[e.v] && (e.c - e.f) >= B)
- {
- ll r = DFS(e.v, min(c, e.c - e.f));
- if (r > 0)
- {
- g[u][j].f += r; // r (литров) жижи течет по ребру u->v
- g[e.v][e.rev].f -= r; // -r (литров) жижи течет по обратному ребру v->u
- return r;
- }
- }
- }
- return 0;
- }
- int main()
- {
- ios_base::sync_with_stdio(0);
- cin.tie(0); cout.tie(0);
- cin >> n >> m;
- vii edges(m); // для ответа (не суть алгоритма)
- for (int i = 0; i < m; ++i)
- {
- // нумерация ребер с 1
- int u, v, c; cin >> u >> v >> c;
- Edge e = Edge(u, v, c);
- Edge inv_e = Edge(v, u, 0); // ребро и обратное ребро
- g[u].push_back(e);
- g[v].push_back(inv_e);
- g[u][g[u].size() - 1].rev = g[v].size() - 1;
- g[v][g[v].size() - 1].rev = g[u].size() - 1;
- edges[i] = { u, g[u].size() - 1 };
- }
- // АЛГОРИТМ ФОРДА-ФАЛКЕРСОНА (С МАШТАБИРОВАНИЕМ)
- for (; B > 0; B /= 2)
- {
- while (true)
- {
- // НУМЕРАЦИЯ ВЕРШИН ОТ 1 ДО n
- for (int i = 1; i <= n; ++i) visited[i] = false;
- ll r = DFS(1, INF);
- if (r == 0) break;
- }
- }
- // Подсчет максимального потока: сумма всех потоков из вершины s (1 = s в данной задаче)
- ll ans = 0;
- for (int j = 0; j < g[1].size(); ++j)
- ans += g[1][j].f;
- cout << ans << "\n";
- for (int i = 0; i < m; ++i)
- {
- int u = edges[i].first, pos = edges[i].second;
- cout << g[u][pos].f << "\n";
- }
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement