Cod sursa(job #3158918)

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

#define INF 1e9

using namespace std;

class MaxFlow {
  private:
    int n;
    vector<vector<int>> neighbours;
    vector<vector<int>> flow, capacity;
    vector<int> excess, current_arc, label;
    queue<int> excess_vertices;

    void push(int u, int v) {
        int pushed_flow = min(excess[u], capacity[u][v] - flow[u][v]);

        if (pushed_flow == 0) {
            return;
        }

        flow[u][v] += pushed_flow;
        flow[v][u] -= pushed_flow;
        excess[u] -= pushed_flow;
        excess[v] += pushed_flow;

        if (excess[v] == pushed_flow) {
            excess_vertices.push(v);
        }
    }

    void relabel(int node) {
        int new_label = INF;

        for (auto neighbour : neighbours[node]) {
            if (capacity[node][neighbour] - flow[node][neighbour] > 0) {
                new_label = min(new_label, label[neighbour] + 1);
            }
        }

        label[node] = new_label;
    }

    void discharge(int node) {
        while (excess[node]) {
            if (current_arc[node] == (int)neighbours[node].size()) {
                current_arc[node] = 0;
                relabel(node);
            } else {
                int neighbour = neighbours[node][current_arc[node]];
                if (capacity[node][neighbour] - flow[node][neighbour] && label[node] == label[neighbour] + 1) {
                    push(node, neighbour);
                } else {
                    current_arc[node]++;
                }
            }
        }
    }

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

  public:
    MaxFlow(int n) : n(n) {
        flow.resize(n, vector<int>(n, 0));
        capacity.resize(n, vector<int>(n, 0));
        excess.resize(n, 0);
        label.resize(n, 0);
        current_arc.resize(n, 0);
        neighbours.resize(n);
    }

    void add_edge(int u, int v, int cap) {
        neighbours[u].push_back(v);
        neighbours[v].push_back(u);
        capacity[u][v] += cap;
    }

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

        excess[source] = INF;
        label[source] = n;

        for (int i = 0; i < n; i++) {
            if (i == source) {
                continue;
            }

            if (capacity[source][i] > 0) {
                push(source, i);
            }
        }

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

            if (node == source || node == sink)
                continue;

            discharge(node);
        }

        int max_flow = 0;
        for (int i = 0; i < n; i++) {
            max_flow += flow[i][sink];
        }

        return max_flow;
    }
};

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

    int n, m, x, y, c;

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

    MaxFlow mf(n);

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

    printf("%d\n", mf.max_flow(0, n - 1));

    return 0;
}