Cod sursa(job #2886356)

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

class Graph{
public:
    const int N;
    vector<vector<int>> neighbors;
    vector<vector<int>> capacity;

public:
    Graph(const int& N): N(N){
        neighbors.resize(N);
        capacity.assign(N, vector<int>(N));
    }

    void addEdge(int x, int y, int c){
        neighbors[x].push_back(y);
        neighbors[y].push_back(x);
        capacity[x][y] = c;
    }

    int computeMaxCapacity() const{
        int maxCapacity = capacity[0][0];
        for(int i = 0; i < N; ++i){
            for(int j = 0; j < N; ++j){
                maxCapacity = max(maxCapacity, capacity[i][j]);
            }
        }
        return maxCapacity;
    }
};

class EdmondsKarp{
private:
    const Graph& G;
    const int N;
    const int SRC;
    const int DEST;
    const int INF = 1e8;
    vector<vector<int>> f;
    vector<int> visIdOf;
    vector<int> prev;
    int visId;

    void bfs(int capacityThreshold){
        queue<int> q;
        q.push(SRC);
        visIdOf[SRC] = visId;
        while(!q.empty()){
            int node = q.front();
            q.pop();

            for(int nextNode: G.neighbors[node]){
                int remainingCapacity = G.capacity[node][nextNode] - f[node][nextNode];
                if(visIdOf[nextNode] != visId && remainingCapacity >= capacityThreshold){
                    visIdOf[nextNode] = visId;
                    prev[nextNode] = node;
                    q.push(nextNode);
                }
            }
        }
    }

    int augmentingPaths(int capacityThreshold){
        bfs(capacityThreshold);

        int deltaSum = 0;
        if(visIdOf[DEST] == visId){
            for(int prevDest: G.neighbors[DEST]){
                if(visIdOf[prevDest] != visId){
                    continue;
                }
                int delta = G.capacity[prevDest][DEST] - f[prevDest][DEST];
                for(int node = prevDest; node != SRC && delta >= capacityThreshold; node = prev[node]){
                    int remainingCapacity = G.capacity[prev[node]][node] - f[prev[node]][node];
                    delta = min(delta, remainingCapacity);
                }
                if(delta >= capacityThreshold){
                    f[prevDest][DEST] += delta;
                    f[DEST][prevDest] -= delta;
                    for(int node = prevDest; node != SRC && delta >= capacityThreshold; node = prev[node]){
                        f[prev[node]][node] += delta;
                        f[node][prev[node]] -= delta;
                    }
                    deltaSum += delta;
                }
            }
        }

        return deltaSum;
    }

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

    int computeMaxFlow(){
        f.assign(N, vector<int>(N, 0));
        visIdOf.resize(N);
        prev.resize(N);
        visId = 0;

        int maxFlow = 0;
        int maxCapacity = G.computeMaxCapacity();
        int capacityThreshold = 1;
        while(capacityThreshold < maxCapacity){
            capacityThreshold *= 2;
        }

        while(capacityThreshold > 0){
            bool containsAugmentingPath = true;
            while(containsAugmentingPath){
                visId += 1;
                int deltaSum = augmentingPaths(capacityThreshold);
                if(deltaSum > 0){
                    maxFlow += deltaSum;
                }else{
                    containsAugmentingPath = false;
                }
            }
            capacityThreshold /= 2;
        }

        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 << EdmondsKarp(G, 0, N - 1).computeMaxFlow();

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