Cod sursa(job #2049249)

Utilizator retrogradLucian Bicsi retrograd Data 26 octombrie 2017 23:27:30
Problema Cuplaj maxim in graf bipartit Scor 90
Compilator cpp Status done
Runda Arhiva educationala Marime 3.15 kb
#include <bits/stdc++.h>

using namespace std;

// Source: e-maxx.ru
// Tested with: VOJ - NKFLOW, VOJ - MCQUERY (Gomory Hu)

// Usage:
// MaxFlow flow(n)
// For each edge: flow.addEdge(u, v, c, edge_id)
// flow.getMaxFlow(s, t)
// flow.trace()
// Index from 0

// Tested:
// - https://open.kattis.com/problems/maxflow
const int INF = 2e9;
 
struct Edge {
    int a, b, cap, flow, id;
};

struct MaxFlow {
    int n, s, t;
    vector<int> d, ptr, q;
    vector< Edge > e;
    vector< vector<int> > g;

    MaxFlow(int n) : n(n), d(n), ptr(n), q(n), g(n) {}

    void addEdge(int a, int b, int cap, int id) {
        Edge e1 = { a, b, cap, 0, id };
        Edge e2 = { b, a, 0, 0, -1 };
        g[a].push_back( (int) e.size() );
        e.push_back(e1);
        g[b].push_back( (int) e.size() );
        e.push_back(e2);
    }
    int getMaxFlow(int _s, int _t) {
        s = _s; t = _t;
        int flow = 0;
        for (;;) {
            if (!bfs()) break;
            for (int i = 0; i < n; ++i) ptr[i] = 0;
            while (int pushed = dfs(s, INF))
                flow += pushed;
        }
        return flow;
    }

    vector<int> trace() {
        bfs();
        vector<int> res;
        for(auto edge : e) {
            if (edge.flow == edge.cap) {
                res.push_back(edge.id);
            }
        }
        return res;
    }

private:
    bool bfs() {
        int qh = 0, qt = 0;
        q[qt++] = s;
        fill(d.begin(), d.end(), -1);
        d[s] = 0;

        while (qh < qt && d[t] == -1) {
            int v = q[qh++];
            for (int i = 0; i < (int)g[v].size(); ++i) {
                int id = g[v][i], to = e[id].b;
                if (d[to] == -1 && e[id].flow < e[id].cap) {
                    q[qt++] = to;
                    d[to] = d[v] + 1;
                }
            }
        }
        return d[t] != -1;
    }

    int dfs (int v, int flow) {
        if (!flow) return 0;
        if (v == t) return flow;
        for (; ptr[v] < (int)g[v].size(); ++ptr[v]) {
            int id = g[v][ptr[v]],
                to = e[id].b;
            if (d[to] != d[v] + 1) continue;
            int pushed = dfs(to, min(flow, e[id].cap - e[id].flow));
            if (pushed) {
                e[id].flow += pushed;
                e[id^1].flow -= pushed;
                return pushed;
            }
        }
        return 0;
    }
};

int main() {
    freopen("cuplaj.in", "r", stdin);
    freopen("cuplaj.out", "w", stdout);
    ios_base::sync_with_stdio(false);

    int n, m, e; cin >> n >> m >> e;
    MaxFlow flow(n + m + 2);
    int s = n + m, d = n + m + 1;
    
    vector<int> To(e), From(e);
    for (int i = 0; i < e; ++i) {
        cin >> From[i] >> To[i];
        --From[i]; --To[i];
        flow.addEdge(From[i], To[i] + n, 1, i);
    }

    for (int i = 0; i < n; ++i)
        flow.addEdge(s, i, 1, -1);
    for (int i = 0; i < m; ++i)
        flow.addEdge(i + n, d, 1, -1);

    int maxFlow = flow.getMaxFlow(s, d);
    cout << maxFlow << endl;
    vector<int> ids = flow.trace();
    cerr << ids.size() << " edges " << endl;
    for (auto x : ids) {
        if (x != -1) {
            cout << From[x] + 1 << " " << To[x] + 1 << '\n';
        }
    }
    return 0;
}