Cod sursa(job #1862280)

Utilizator depevladVlad Dumitru-Popescu depevlad Data 29 ianuarie 2017 18:30:32
Problema Flux maxim Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 4.14 kb
#include <bits/stdc++.h>

#define fi first
#define se second

using namespace std;

template <bool Directed>
class flowNetwork {
    private:
        class Edge {
            public:
                int From;
                int To;
                int Capacity;
                int Flow;

                Edge(
                  int __From = 0,
                  int __To = 0,
                  int __Capacity = 0,
                  int __Flow = 0
                ) {
                    From = __From;
                    To = __To;
                    Capacity = __Capacity;
                    Flow = __Flow;
                }
        };

        int Size;
        int Source;
        int Sink;
        int numEdges;
        vector <Edge> Edges;
        vector <vector <int>> G;
        static const int INF = numeric_limits <int> :: max();

        inline void linkNodes(int x, int y, int c) {
            Edges.push_back(Edge(x, y, c, 0));
            G[x].push_back(numEdges);
            numEdges++;

            Edges.push_back(Edge(y, x, (Directed == true ? 0 : c), 0));
            G[y].push_back(numEdges);
            numEdges++;
        }

        pair <bool, vector <int>> findPath() {
            vector <int> Parent(Size, -1);
            queue <int> Q;
            Parent[Source] = 0;
            for (Q.push(Source); Q.empty() == false; Q.pop()) {
                int x = Q.front();
                if (x != Sink) {
                    for (int i: G[x]) {
                        if (Edges[i].Flow < Edges[i].Capacity) {
                            int y = Edges[i].To;
                            if (Parent[y] == -1) {
                                Parent[y] = i;
                                Q.push(y);
                            }
                        }
                    }
                }
            }
            Parent[Source] = -1;
            if (Parent[Sink] != -1) return {true, Parent};
            else return {false, vector <int>()};
        }

    public:
        flowNetwork(
          const int __Size,
          const int __Source,
          const int __Sink,
          const vector <pair <int, pair <int, int>>> &Edges
        ) {
            Size = __Size;
            Source = __Source;
            Sink = __Sink;
            numEdges = 0;
            G = vector <vector <int>>(Size, vector <int>());
            for (const pair <int, pair <int, int>> &Edge: Edges) {
                int x;
                int y;
                int c = Edge.fi;
                tie(x, y) = Edge.se;
                linkNodes(x, y, c);
            }
        }

        int flowSolve() {
            int flowSum = 0;
            bool Stop = false;
            do {
                bool foundSolution;
                vector <int> Parent;
                tie(foundSolution, Parent) = findPath();
                if (foundSolution == false) {
                    Stop = true;
                }
                else {
                    for (int i: G[Sink]) {
                        if (Parent[Edges[i].To] != -1) {
                            int flowCurrent = INF;
                            Parent[Sink] = i ^ 1;
                            for (int j = Parent[Sink]; j != -1; j = Parent[Edges[j].From]) {
                                flowCurrent = min(flowCurrent, Edges[j].Capacity - Edges[j].Flow);
                            }
                            for (int j = Parent[Sink]; j != -1; j = Parent[Edges[j].From]) {
                                Edges[j].Flow += flowCurrent;
                                Edges[j ^ 1].Flow -= flowCurrent;
                            }
                            flowSum += flowCurrent;
                        }
                    }
                }
            } while (Stop == false);
            return flowSum;
        }
};

int n;
int m;
vector <pair <int, pair <int, int>>> Edges;

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

    cin >> n;
    cin >> m;
    for (int i = 1; i <= m; i++) {
        int x;
        int y;
        int c;
        cin >> x >> y >> c;
        Edges.push_back({c, {x, y}});
    }

    flowNetwork <true> F(n + 1, 1, n, Edges);
    cout << F.flowSolve() << "\n";

    return 0;
}