Cod sursa(job #1112344)

Utilizator a_h1926Heidelbacher Andrei a_h1926 Data 19 februarie 2014 18:27:55
Problema Flux maxim Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 4.42 kb
#include <fstream>
#include <vector>
#include <queue>
#include <algorithm>

using namespace std;

class Graph {
  public:
    class Edge {
      public:
        static const int oo = 0x3f3f3f3f;

        Edge(const int _from, const int _to, const int _capacity):
          from(_from),
          to(_to),
          capacity(_capacity),
          flow(0) {}

        int From() const {
            return from;
        }

        int To() const {
            return to;
        }

        int Capacity() const {
            return capacity;
        }

        int &Flow() {
            return flow;
        }

        bool IsSaturated() const {
            return flow == capacity;
        }

      private:
        int from, to, capacity, flow;
    };

    static const int NIL = -1;

    Graph(const int _v = 0):
      v(_v),
      edgeCount(0),
      vertexEdges(vector< vector<int> >(_v, vector<int>())),
      edges(vector<Edge>()) {}

    int V() const {
        return v;
    }

    Edge GetEdge(const int e) const {
        return edges[e];
    }

    vector<int>::const_iterator EdgesBegin(const int x) const {
        return vertexEdges[x].begin();
    }

    vector<int>::const_iterator EdgesEnd(const int x) const {
        return vertexEdges[x].end();
    }

    void AddEdge(const Edge &e) {
        vertexEdges[e.From()].push_back(edgeCount++);
        edges.push_back(e);
    }

    int MaximumFlow(const int source, const int sink) {
        InitializeFlowNetwork();
        int maxFlow = 0;
        vector<int> father;
        while (BFS(source, sink, father)) {
            for (vector<int>::iterator e = vertexEdges[sink].begin(); e != vertexEdges[sink].end(); ++e) {
                if (father[edges[*e].To()] == NIL || edges[NonEdge(*e)].IsSaturated())
                    continue;
                father[sink] = NonEdge(*e);
                int currentFlow = Edge::oo;
                for (int x = sink; x != source; x = edges[father[x]].From())
                    currentFlow = min(currentFlow, edges[father[x]].Capacity() - edges[father[x]].Flow());
                for (int x = sink; x != source; x = edges[father[x]].From()) {
                    edges[father[x]].Flow() += currentFlow;
                    edges[NonEdge(father[x])].Flow() -= currentFlow;
                }
                maxFlow += currentFlow;
            }
        }
        ClearFlowNetwork();
        return maxFlow;
    }

  private:
    int v, edgeCount;
    vector< vector<int> > vertexEdges;
    vector<Edge> edges;

    int NonEdge(const int e) const {
        if (e < edgeCount)
            return e + edgeCount;
        else
            return e - edgeCount;
    }

    void InitializeFlowNetwork() {
        for (int e = 0; e < edgeCount; ++e) {
            edges[e].Flow() = 0;
            edges.push_back(Edge(edges[e].To(), edges[e].From(), 0));
            vertexEdges[edges[e].To()].push_back(NonEdge(e));
        }
    }

    bool BFS(const int source, const int sink, vector<int> &father) const {
        father = vector<int>(v, NIL);
        father[source] = 2 * edgeCount;
        queue<int> q;
        for (q.push(source); !q.empty(); q.pop()) {
            int x = q.front();
            if (x == sink)
                continue;
            for (vector<int>::const_iterator e = vertexEdges[x].begin(); e != vertexEdges[x].end(); ++e) {
                if (father[edges[*e].To()] == NIL && !edges[*e].IsSaturated()) {
                    father[edges[*e].To()] = *e;
                    q.push(edges[*e].To());
                }
            }
        }
        return (father[sink] != NIL);
    }

    void ClearFlowNetwork() {
        for (int e = edgeCount - 1; e >= 0; --e)
            vertexEdges[edges[e].To()].pop_back();
        for (int e = 0; e < edgeCount; ++e)
            edges.pop_back();
    }
};

Graph G;
int MaxFlow;

void Solve() {
    MaxFlow = G.MaximumFlow(0, G.V() - 1);
}

void Read() {
    ifstream cin("maxflow.in");
    int v, e;
    cin >> v >> e;
    G = Graph(v);
    for (; e > 0; --e) {
        int from, to, capacity;
        cin >> from >> to >> capacity;
        G.AddEdge(Graph::Edge(--from, --to, capacity));
    }
    cin.close();
}

void Print() {
    ofstream cout("maxflow.out");
    cout << MaxFlow << "\n";
    cout.close();
}

int main() {
    Read();
    Solve();
    Print();
    return 0;
}