Cod sursa(job #2888588)

Utilizator buzu.tudor67Tudor Buzu buzu.tudor67 Data 11 aprilie 2022 17:06:06
Problema Flux maxim Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.1 kb
#include <bits/stdc++.h>
using namespace std;

class Edge{
public:
    int from;
    int to;
    int capacity;
    int flow;

    Edge(int from, int to, int capacity, int flow = 0):
         from(from), to(to), capacity(capacity), flow(flow){
    }

    int getRemainingCapacity() const{
        return capacity - flow;
    }
};

class Graph{
public:
    const int N;
    vector<Edge> edges;
    vector<vector<int>> edgeIndices;

public:
    Graph(const int& N): N(N){
        edgeIndices.resize(N);
    }

    void addEdge(int from, int to, int c){
        edges.push_back(Edge(from, to, c));
        edges.push_back(Edge(to, from, 0));
        edgeIndices[from].push_back((int)edges.size() - 2);
        edgeIndices[to].push_back((int)edges.size() - 1);
    }
};

class Dinic{
private:
    Graph& G;
    const int N;
    const int SRC;
    const int DEST;
    const int INF = 1e8;
    vector<int> dist;
    vector<int> edgeStartIdx;

    int bfs(){
        fill(dist.begin(), dist.end(), INF);
        
        queue<int> q;
        q.push(SRC);
        dist[SRC] = 0;
        while(!q.empty() && dist[DEST] == INF){
            int node = q.front();
            q.pop();

            for(int idx: G.edgeIndices[node]){
                Edge& edge = G.edges[idx];
                int nextNode = edge.to;
                if(edge.getRemainingCapacity() > 0 && dist[nextNode] == INF){
                    dist[nextNode] = 1 + dist[node];
                    q.push(nextNode);
                }
            }
        }

        return (dist[DEST] != INF);
    }

    int dfs(int node, int minDelta){
        if(node == DEST){
            return minDelta;
        }
        for(; edgeStartIdx[node] < (int)G.edgeIndices[node].size(); ++edgeStartIdx[node]){
            int idx = G.edgeIndices[node][edgeStartIdx[node]];
            Edge& edge = G.edges[idx];
            Edge& edgeRev = G.edges[idx ^ 1];
            int nextNode = edge.to;
            if(edge.getRemainingCapacity() > 0 && dist[node] + 1 == dist[nextNode]){
                int delta = dfs(nextNode, min(minDelta, edge.getRemainingCapacity()));
                if(delta > 0){
                    edge.flow += delta;
                    edgeRev.flow -= delta;
                    return delta;
                }
            }
        }
        return 0;
    }

public:
    Dinic(Graph& G, const int& SRC, const int& DEST):
          G(G), N(G.N), SRC(SRC), DEST(DEST){
    }

    int computeMaxFlow(){
        dist.resize(N);
        edgeStartIdx.resize(N);

        int maxFlow = 0;
        while(bfs()){
            fill(edgeStartIdx.begin(), edgeStartIdx.end(), 0);
            int delta = INF;
            while(delta > 0){
                delta = dfs(SRC, INF);
                maxFlow += delta;
            }
        }

        return maxFlow;
    }
};

int main(){
    ifstream cin("maxflow.in");
    ofstream cout("maxflow.out");

    int N, M;
    cin >> N >> M;

    Graph G(N);
    int x, y, c;
    for(int i = 0; i < M; ++i){
        cin >> x >> y >> c;
        G.addEdge(x - 1, y - 1, c);
    }

    cout << Dinic(G, 0, N - 1).computeMaxFlow();

    cin.close();
    cout.close();
    return 0;
}