Cod sursa(job #2885429)

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

using namespace std;

// #define int long long

template < typename EDGE_FLOW_DATA , typename NETWORK_FLOW_DATA >
    struct Dinic {
        struct Edge {
            int to; EDGE_FLOW_DATA flow, cap;
        };

        const int MAXDIST = 1e9;
        const NETWORK_FLOW_DATA MAXFLOW = std::numeric_limits<NETWORK_FLOW_DATA>::max();

        int n, source, sink;
        vector<vector<int>> adj;
        vector<int> edge_ind, dist;
        vector<Edge> edges;

        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=to, .flow=0, .cap=cap});
            edges.push_back({.to=from, .flow=0, .cap=0});

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

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

            queue<int> q; q.push(source);
            dist[source] = 0;

            while(!q.empty()) {
                auto cnt = q.front(); q.pop();

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

            return dist[sink] != MAXDIST;
        }

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

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

                auto &e = edges[adj[node][ind]];

                if(dist[e.to] != dist[node] + 1) continue;

                if(e.flow < e.cap) {
                    NETWORK_FLOW_DATA cnt_pushed = do_push(e.to, min<NETWORK_FLOW_DATA>(e.cap - e.flow, flow));
                    pushed += cnt_pushed; flow -= cnt_pushed;

                    // cerr << "Pushed from " << node << " to " << e.to << " some " << cnt_pushed << endl;

                    edges[adj[node][ind]    ].flow += cnt_pushed;
                    edges[adj[node][ind] ^ 1].flow -= cnt_pushed;
                }
            }
            return pushed;
        }

        NETWORK_FLOW_DATA get_flow() {
            NETWORK_FLOW_DATA answer = 0;
            while(do_bfs()) {
                // for(int i = 1; i <= n; i++)
                //    cerr << i << ": " << dist[i] << endl;

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

                while(true) {
                    NETWORK_FLOW_DATA pushed = do_push(source, MAXFLOW);
                    answer += pushed;

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

#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<int32_t, int64_t> 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';
}