Cod sursa(job #2822263)

Utilizator Cosmin2004_InfoMoldoveanu Cosmin Cosmin2004_Info Data 23 decembrie 2021 19:15:12
Problema Cuplaj maxim in graf bipartit Scor 90
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.46 kb
#include <bits/stdc++.h>

using namespace std;
#ifdef INFOARENA
ifstream fin("cuplaj.in");
ofstream fout("cuplaj.out");
#define cin fin
#define cout fout
#endif // INFOARENA
class Flow {
    const int flow_max = 1e9;

    int n, s, t;
    vector <int> lvl, rem;
    vector <vector <int>> g;

    bool bfs() {
        fill(lvl.begin(), lvl.end(), 0);
        queue <int> q; q.push(s); lvl[s] = 1;
        while(!q.empty()) {
            int top = q.front(); q.pop();
            for(int id : g[top])
                if(!lvl[edges[id].to] && edges[id].c) {
                    lvl[edges[id].to] = lvl[top] + 1;
                    q.push(edges[id].to);
                }
        }
        return lvl[t];
    }
public:
    int k;
    struct Edge {
        int from, to, c;
        Edge(int a, int b, int _c) : from(a), to(b), c(_c) {}
    };
    vector <Edge> edges;
    Flow(int _n, int _s, int _t) : n(_n), s(_s), t(_t), k(0), lvl(_n + 1, 0), rem(_n + 1, 0), g(_n + 1) {}

    void add_edge(int u, int v, int w) {
        edges.emplace_back(u, v, w);
        edges.emplace_back(v, u, 0);
        g[u].push_back(k++);
        g[v].push_back(k++);
    }

    int dfs(int u, int flow) {
        if(flow == 0) return 0;
        if(u == t) return flow;
        for(int& cid = rem[u]; cid < (int)g[u].size(); cid++) {
            int id = g[u][cid];
            int v = edges[id].to;
            if(!edges[id].c || lvl[v] != lvl[u] + 1) continue;
            int f = dfs(v, min(flow, edges[id].c));
            if(f == 0) continue;
            edges[id].c -= f;
            edges[id ^ 1].c += f;
            return f;
        }
        return 0;
    }

    int dinic() {
        int f = 0;
        while(bfs()) {
            fill(rem.begin(), rem.end(), 0);
            while(int flow = dfs(s, flow_max))
                f += flow;
        }
        return f;
    }
};

int main()
{
    int n, m, e, u, v;
    cin >> n >> m >> e;
    Flow f(n + m + 1, 0, n + m + 1);
    for(int i = 1; i <= n; i++) f.add_edge(0, i, 1);
    for(int i = 1; i <= m; i++) f.add_edge(i + n, n + m + 1, 1);
    for(int i = 1; i <= e; i++)
        cin >> u >> v,
        f.add_edge(u, n + v, 1);
    cout << f.dinic() << "\n";
    for(int i = 1; i < f.k; i += 2) {
        Flow :: Edge e = f.edges[i];
        swap(e.to, e.from);
        if(e.from != 0 && e.to != n + m + 1 && e.c)
            cout << e.from << " " << e.to - n << "\n";
    }
    return 0;
}