Cod sursa(job #2240412)

Utilizator freak93Adrian Budau freak93 Data 13 septembrie 2018 11:13:32
Problema Flux maxim Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 4.12 kb
#include <iostream>
#include <fstream>
#include <vector>
#include <algorithm>
#include <queue>
#include <tuple>

using namespace std;

class Graph {
  public:
    Graph(int size):
        m_capacity(size, vector<int>(size, 0)),
        m_edges(size),
        m_size(size) {}

    void add_edge(int from, int to, int capacity) {
        m_capacity[from][to] += capacity;
        m_edges[from].push_back(to);
        m_edges[to].push_back(from);
    }

    void remove_duplicates() {
        for (auto &edges: m_edges) {
            sort(edges.begin(), edges.end());
            edges.erase(unique(edges.begin(), edges.end()), edges.end());
        }
    }

    int max_flow(int source, int destination) {
        int answer = 0;
        while (true) {
            auto edges = get_level_graph_edges(source, destination);

            if (edges.empty())
                return answer;

            int flow;
            do {
                flow = tidal_phase(edges, source, destination);
                answer += flow;
            } while (flow > 0);
        }

        return answer;
    }

  private:
    vector< pair<int, int> > get_level_graph_edges(int source, int destination) {
        // Find accessible nodes from destination, not really needed but speeds up a bit
        queue<int> Q;
        Q.push(destination);
        vector<int> level(m_size, -2);
        level[destination] = 0;
        while (!Q.empty()) {
            int x = Q.front();
            Q.pop();

            if (x == source)
                break;

            for (auto &y : m_edges[x])
                if (m_capacity[y][x] > 0 && level[y] == -2) {
                    level[y] = level[x] + 1;
                    Q.push(y);
                }
        }

        // level graph edges
        vector< pair<int, int> > edges;
        if (level[source] == -2) {
            return edges;
        }

        while (!Q.empty())
            Q.pop();
        Q.push(source);
        vector<bool> used(m_size, false);
        used[source] = true;

        while (!Q.empty()) {
            int x = Q.front();
            Q.pop();

            for (auto &y : m_edges[x])
                if (m_capacity[x][y] > 0 && level[y] == level[x] - 1) {
                    edges.emplace_back(x, y);
                    if (used[y] == false) {
                        used[y] = true;
                        Q.push(y);
                    }
                }
        }
        return edges;
    }

    int tidal_phase(const vector< pair<int, int> > &edges, int source, int destination) {
        vector<int> high(m_size, 0);
        high[source] = numeric_limits<int>::max();

        vector<int> permitted(edges.size());
        for (int i = 0; i < int(edges.size()); ++i) {
            int from, to; tie(from, to) = edges[i];
            permitted[i] = min(high[from], m_capacity[from][to]);
            high[to] += permitted[i];
        }

        if (high[destination] == 0)
            return 0;

        vector<int> low(m_size, 0);
        low[destination] = high[destination];

        for (int i = edges.size() - 1; i >= 0; --i) {
            int from, to; tie(from, to) = edges[i];
            int limit = min(high[from] - low[from], low[to]);
            permitted[i] = min(permitted[i], limit);
            low[from] += permitted[i];
            low[to] -= permitted[i];
        }

        fill(high.begin(), high.end(), 0);
        high[source] = low[source];

        for (int i = 0; i < int(edges.size()); ++i) {
            int from, to; tie(from, to) = edges[i];
            int flow = min(permitted[i], high[from]);
            high[from] -= flow;
            high[to] += flow;
            m_capacity[from][to] -= flow;
            m_capacity[to][from] += flow;
        }

        return high[destination];
    }

    vector< vector<int> > m_capacity;
    vector< vector<int> > m_edges;
    int m_size;
};

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

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

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

    G.remove_duplicates();
    cout << G.max_flow(0, N - 1) << "\n";
}