Cod sursa(job #2885426)

Utilizator redstonegamer22Andrei Ion redstonegamer22 Data 5 aprilie 2022 23:17:50
Problema Flux maxim Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.13 kb
#include <bits/stdc++.h>

using namespace std;

// #define int long long

struct Dinic {
    struct edge {
        int to, flow, cap;
    };

    const int MAXFLOW = 1e9;
    const int MAXDIST = 1e9;
    int n, source, sink;

    vector<vector<int>> adj;
    vector<edge> edges;
    vector<int> edge_ind;
    vector<int> dist;

    Dinic(int _n, int _source, int _sink) {
        n = _n; source = _source; sink = _sink;

        adj.resize(n + 3);
        edge_ind.resize(n + 3);
        dist.resize(n + 3);
    }

    void add_edge(int from, int to, int cap) {
        edges.push_back({to, 0, cap});
        edges.push_back({from, 0, 0});

        adj[from].push_back(edges.size() - 2);
        adj[to].push_back(edges.size() - 1);
    }

    void do_bfs() {
        for(auto &e : dist) e = MAXDIST;

        queue<int> q;

        dist[source] = 0;
        q.push(source);

        while(!q.empty()) {
            auto cnt = q.front(); q.pop();
            for(auto ind : adj[cnt]) {
                edge &e = edges[ind];
                if(e.flow < e.cap && dist[cnt] + 1 < dist[e.to]) {
                    dist[e.to] = dist[cnt] + 1;
                    q.push(e.to);
                }
            }
        }
    }

    int do_push(int node, int flow) {
        if(node == sink) return flow;

        int pushed = 0;
        for(auto &ind = edge_ind[node]; ind < adj[node].size(); ind++) {
            if(flow == 0) return pushed;

            auto &e = edges[adj[node][ind]];
            // cerr << "A" << node << " " << dist[node] << " " << e.to << " " << dist[e.to] << endl;
            // cerr << "B" << e.flow << " " << e.cap << endl;
            if(dist[e.to] != dist[node] + 1) continue;
            if(e.flow < e.cap) {
                int cnt_pushed = do_push(e.to, min(e.cap - e.flow, flow));

                e.flow += cnt_pushed;
                edges[adj[node][ind] ^ 1].flow -= cnt_pushed;

                pushed += cnt_pushed;
                flow -= cnt_pushed;

                // cerr << "Trying to push from " << node << " to " << e.to << endl;
                // cerr << "Pushed " << cnt_pushed << endl;
            }
        }
        return pushed;
    }

    int get_flow() {
        int ans = 0;
        while(true) {
            do_bfs();

            /*for(int i = 1; i <= n; i++) {
                cerr << i << ": " << dist[i] << endl;
            }*/

            if(dist[sink] == MAXDIST) return ans;

            for(auto &e : edge_ind) e = 0;

            while(true) {
                int pushed = do_push(source, MAXFLOW);
                // cerr << pushed << endl;
                ans += pushed;

                if(pushed == 0) break;
            }
        }
        return ans;
    }
};

#ifndef LOCAL
ifstream in("maxflow.in");
ofstream out("maxflow.out");
#define cin in
#define cout out
#endif // LOCAL

int32_t main() {
    int n, m; cin >> n >> m;
    Dinic solver(n, 1, n);

    for(int i = 0; i < m; i++) {
        int x, y, c; cin >> x >> y >> c;
        solver.add_edge(x, y, c);
    }

    cout << solver.get_flow() << '\n';
}