Cod sursa(job #2679615)

Utilizator RazorBestPricop Razvan Marius RazorBest Data 1 decembrie 2020 00:00:22
Problema Flux maxim Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.68 kb
#include <fstream>
#include <list>
#include <vector>
#include <queue>
#include <cstring>
#include <iostream>

#define DEFAULT_INPUT "maxflow.in"
#define DEFAULT_OUTPUT "maxflow.out"
#define MAX_N 110010

struct edge {
    int y;
    int c;
    int rev; /* index of reversed edge in adjacency list of y */
};


class Graph {

private:
    std::vector<edge> adj[MAX_N];
    std::vector<edge*> level_adj[MAX_N];
    int n, s, t;
    int dist[MAX_N];
    int pt[MAX_N];

    void init() {
        s = 0;
        t = n - 1;
        int is_source, is_sink;

        // suppose there are only one source and one sink
        for (int i = 0; i < n; i++) {
            is_source = 1;
            is_sink = 1;
            for (auto e: adj[i]) {
                if (e.c == 0) {
                    is_source = 0;
                    continue;
                }
                
                is_sink = 0;
            }
            if (is_source) {
                s = i;
            }
            else if (is_sink) {
                t = i;
            }
        }
    }

    int bfs(int node) {
        std::queue<int> q;
        char visited[MAX_N] = {0};

        memset(dist, 0, n * sizeof(*dist));

        q.push(node);
        visited[node] = 1;

        while (!q.empty()) {
            node = q.front();
            q.pop();
           
            if (node == t) {
                return 1;
            }

            // create leveled graph
            for (auto it = adj[node].begin(); it != adj[node].end(); it++) {
                int next_d = dist[node] + 1;

                if (!visited[it->y] && it->c > 0) {
                    visited[it->y] = 1;
                    dist[it->y] = next_d;
                    q.push(it->y);
                }

                if (dist[it->y] == next_d) {
                    level_adj[node].push_back(&(*it));
                }
            }
        }

        return 0;
    }

    int dfs(int node, int flow) {
        if (node == t) {
            return flow;
        }

        int total = 0;

        int expected = dist[node] + 1;
        for (auto it = level_adj[node].begin(); it != level_adj[node].end(); it++) {
            int next = (*it)->y;

            if (dist[next] == expected && (*it)->c > 0) {
                int child_flow = dfs(next, std::min((*it)->c, flow));
                total += child_flow;
                (*it)->c -= child_flow;

                adj[next][(*it)->rev].c += child_flow;
                flow -= child_flow;
                if (flow == 0) {
                    return total;
                }
            }
        }

        return total;
    }


public:
    Graph(int n) {
        this->n = n;
    }

    void add_edge(int x, int y, int c) {
        adj[x].push_back({y, c, (int)adj[y].size()});
        adj[y].push_back({x, 0, (int)(adj[x].size() - 1)});
    }

    int compute_max_flow() {
        int max_flow = 0, flow;
        
        init();

        while (bfs(s)) {
            max_flow += dfs(s, 0x7fffffff);
            for (int i = 0; i < n; i++) {
                level_adj[i].clear();
            }
        }

        return max_flow;
    }
};


int main(int argc, char *argv[]) {
    std::ifstream fin;
    std::ofstream fout;
    
    if (argc == 1) {
        fin.open(DEFAULT_INPUT);
    } else {
        fin.open(argv[1]);
    }

    int n, m, x, y, c;

    fin >> n >> m;
    
    Graph g(n);
    
    for (int i = 0; i < m; i++) {
        fin >> x >> y >> c;
        x--; y--;
        g.add_edge(x, y, c);
    }

    fin.close();

    int max_flow = g.compute_max_flow();

    if (argc < 3) {
        fout.open(DEFAULT_OUTPUT);
        std::cout << "Noo\n";
    } else {
        fout.open(argv[2]);
    }

    fout << max_flow << '\n';

    fout.close();
}