Cod sursa(job #3159100)

Utilizator GabiTulbaGabi Tulba-Lecu GabiTulba Data 20 octombrie 2023 18:02:53
Problema Flux maxim Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.25 kb
#include <bits/stdc++.h>

using namespace std;

class Dinitz {
  private:
    const long long inf = 1LL << 60;

    int n;
    long long minimum_flow;
    vector<vector<long long>> flow, capacity;
    vector<vector<int>> neighbours;
    vector<int> level, current_edge;

    bool BFS(int source, int sink, long long min_flow) {
        queue<int> q;
        q.push(source);
        fill(level.begin(), level.end(), -1);
        level[source] = 0;

        while (!q.empty()) {
            int node = q.front();
            q.pop();

            for (auto neighbour : neighbours[node]) {
                if (capacity[node][neighbour] - flow[node][neighbour] < min_flow || level[neighbour] != -1) {
                    continue;
                }
                level[neighbour] = level[node] + 1;
                q.push(neighbour);
            }
        }

        return level[sink] != -1;
    }

    long long DFS(int node, int sink, long long pushed_flow) {
        if (pushed_flow == 0 || node == sink) {
            return pushed_flow;
        }

        while (current_edge[node] < (int)neighbours[node].size()) {
            int neigh = neighbours[node][current_edge[node]];
            if (level[node] + 1 != level[neigh]) {
                current_edge[node]++;
                continue;
            }

            long long new_pushed_flow = DFS(neigh, sink, min(pushed_flow, capacity[node][neigh] - flow[node][neigh]));
            if (new_pushed_flow == 0) {
                current_edge[node]++;
                continue;
            }

            flow[node][neigh] += new_pushed_flow;
            flow[neigh][node] -= new_pushed_flow;
            return new_pushed_flow;
        }
        return 0;
    }

    void reset_flow() {
        for (int i = 0; i < n; i++) {
            fill(flow[i].begin(), flow[i].end(), 0);
        }
    }

  public:
    Dinitz(int n) : n(n), minimum_flow(1) {
        flow.resize(n, vector<long long>(n, 0));
        capacity.resize(n, vector<long long>(n, 0));
        neighbours.resize(n);
        level.resize(n, 0);
        current_edge.resize(n, 0);
    }

    void add_edge(int x, int y, long long cap) {
        neighbours[x].push_back(y);
        neighbours[y].push_back(x);
        capacity[x][y] += cap;
        while ((minimum_flow << 1) <= capacity[x][y]) {
            minimum_flow <<= 1;
        }
    }

    long long max_flow(int source, int sink) {
        reset_flow();

        long long max_flow = 0;

        for (int min_flow = minimum_flow; min_flow > 0; min_flow >>= 1) {
            while (BFS(source, sink, min_flow)) {
                fill(current_edge.begin(), current_edge.end(), 0);

                long long pushed_flow = DFS(source, sink, inf);
                while (pushed_flow) {
                    max_flow += pushed_flow;
                    pushed_flow = DFS(source, sink, inf);
                }
            };
        }

        return max_flow;
    }
};

int main() {
    freopen("maxflow.in", "r", stdin);
    freopen("maxflow.out", "w", stdout);

    int n, m, x, y;
    long long c;

    scanf("%d%d", &n, &m);

    Dinitz dinitz(n);

    for (int i = 1; i <= m; i++) {
        scanf("%d%d%lld", &x, &y, &c);
        x--, y--;
        dinitz.add_edge(x, y, c);
    }

    printf("%lld\n", dinitz.max_flow(0, n - 1));

    return 0;
}