Cod sursa(job #3153565)

Utilizator rastervcrastervc rastervc Data 30 septembrie 2023 11:28:38
Problema Flux maxim Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.39 kb
#include <bits/stdc++.h>

using namespace std;

constexpr long long INF = 1e18;

struct FlowEdge {
    int from, to;
    long long capacity;
    long long flow;

    inline FlowEdge(int from, int to, long long capacity)
        : from(from), to(to), capacity(capacity), flow() {}
};

class Dinitz {
    vector<FlowEdge> edges;
    vector<vector<int>> inc;
    vector<int> level, ptr;
    int V, E, s, t, max_f;
    bool solved;

    inline bool generate_level_graph() {
        fill(level.begin(), level.end(), -1);
        level[s] = 0;

        queue<int> q;
        q.push(s);

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

            for (const int id : inc[node]) {
                if (edges[id].capacity - edges[id].flow == 0) continue;
                if (level[edges[id].to] != -1) continue;
                level[edges[id].to] = level[node] + 1;
                q.push(edges[id].to);
            }
        }

        return level[t] != -1;
    }

    inline long long find_augmenting_path(int node, long long pushed = INF) {
        if (node == t || pushed == 0) return pushed;

        for (; ptr[node] < (int)inc[node].size(); ++ptr[node]) {
            const int id = inc[node][ptr[node]];
            const int to = edges[id].to;
            if (level[node] + 1 != level[to] || edges[id].capacity - edges[id].flow == 0)
                continue;
            long long tr = find_augmenting_path(to, min(pushed, edges[id].capacity - edges[id].flow));
            if (tr == 0) continue;
            edges[id].flow += tr;
            edges[id ^ 1].flow -= tr;
            return tr;
        }

        return 0;
    }

public:
    Dinitz(int V, int s, int t)
        : V(V), E(), s(s), t(t), solved(false) {
        inc.resize(V);
        level.resize(V);
        ptr.resize(V);
    }

    inline void add_edge(int from, int to, long long capacity) {
        edges.emplace_back(from, to, capacity);
        edges.emplace_back(to, from, 0);
        inc[from].push_back(E);
        inc[to].push_back(E + 1);
        E += 2;
        solved = false;
    }

    inline long long max_flow() {
        if (solved) return max_f;

        for (FlowEdge &edge : edges)
            edge.flow = 0;

        long long f = 0;
        for (;;) {
            fill(level.begin(), level.end(), -1);
            if (!generate_level_graph())
                break;
            
            fill(ptr.begin(), ptr.end(), 0);
            while (long long pushed = find_augmenting_path(s))
                f += pushed;
        }

        solved = true;
        return max_f = f;
    }
};

int main() {
    ifstream fin("maxflow.in");
    ofstream fout("maxflow.out");

    int V, E;
    fin >> V >> E;

    vector<FlowEdge> edges;
    vector<int> in(V, 0), out(V, 0);

    int from, to, capacity;
    for (int i = 0; i < E; ++i) {
        fin >> from >> to >> capacity;
        edges.emplace_back(from - 1, to - 1, capacity);
        ++out[from - 1];
        ++in[to - 1];
    }

    int s, t;
    for (int i = 0; i < V; ++i)
        if (in[i] == 0) s = i;
        else if (out[i] == 0) t = i;

    Dinitz dinitz(V, s, t);
    for (const FlowEdge &edge : edges)
        dinitz.add_edge(edge.from, edge.to, edge.capacity);

    fout << dinitz.max_flow();

    fin.close();
    fout.close();
    return 0;
}