Cod sursa(job #1864879)

Utilizator msciSergiu Marin msci Data 1 februarie 2017 04:47:36
Problema Cuplaj maxim in graf bipartit Scor 12
Compilator cpp Status done
Runda Arhiva educationala Marime 3.45 kb
#include <bits/stdc++.h>

using namespace std;

struct Dinic {
    static const int InfCapacity = 0x3f3f3f3f;

    struct Edge {
        int to;
        int capacity;
        int rev;
    };

    vector< vector<Edge> > g;

    void init(int n) {
        g.assign(n, vector<Edge>());
    }

    void add(int i, int j, int capacity) {
        Edge e, f;
        e.to = j, f.to = i;
        e.capacity = capacity, f.capacity = 0;
        g[i].push_back(e);
        g[j].push_back(f);
        g[i].back().rev = (int) g[j].size() - 1;
        g[j].back().rev = (int) g[i].size() - 1;
    }

    void addB(int i, int j, int capacity) {
        Edge e, f;
        e.to = j, f.to = i;
        e.capacity = capacity, f.capacity = capacity;
        g[i].push_back(e);
        g[j].push_back(f);
        g[i].back().rev = (int) g[j].size() - 1;
        g[j].back().rev = (int) g[i].size() - 1;
    }

    int maximum_flow(int s, int t) {
        int n = (int) g.size();
        vector<int> level(n);
        int total = 0;
        bool update;
        do {
            update = false;
            fill(level.begin(), level.end(), -1);
            level[s] = 0;
            queue<int> q;
            q.push(s);
            for (int d = n; !q.empty() && level[q.front()] < d;) {
                int u = q.front();
                q.pop();
                if (u == t) {
                    d = level[u];
                }
                for (Edge &e : g[u]) {
                    if (e.capacity > 0 && level[e.to] == -1) {
                        q.push(e.to);
                        level[e.to] = level[u] + 1;
                    }
                }
            }
            vector<int> iter(n);
            for (int i = 0; i < n; i++) {
                iter[i] = (int) g[i].size() - 1;
            }
            while (true) {
                int f = augment(level, iter, s, t, InfCapacity);
                if (f == 0) {
                    break;
                }
                total += f;
                update = true;
            }
        } while (update);
        return total;
    }

    int augment(vector<int>& level, vector<int>& iter, int u, int t, int f) {
        if (u == t || f == 0) {
            return f;
        }
        int lv = level[u];
        if (lv == -1) {
            return 0;
        }
        level[u] = -1;
        for (; iter[u] >= 0; --iter[u]) {
            Edge &e = g[u][iter[u]];
            if (level[e.to] <= lv) {
                continue;
            }
            int l = augment(level, iter, e.to, t, min(f, e.capacity));
            if (l == 0) continue;
            e.capacity -= l;
            g[e.to][e.rev].capacity += l;
            level[u] = lv;
            return l;
        }
        return 0;
    }
};

int main() {
    freopen("cuplaj.in", "r", stdin);
    freopen("cuplaj.out", "w", stdout);
    int n, m, e;
    scanf("%d %d %d", &n, &m, &e);
    Dinic mf; mf.init(n + m + 2);
    for (int i = 0; i < e; i++) {
        int a, b;
        scanf("%d %d", &a, &b);
        mf.add(a, n + b + 1, 1);
    }
    int s = 0, t = n + m + 1;
    for (int i = 1; i <= n; i++) mf.add(s, i, 1);
    for (int i = n + 1; i <= n + m + 1; i++) mf.add(i, t, 1);
    printf("%d\n", mf.maximum_flow(s, t));
    vector< vector<Dinic::Edge> > g = mf.g;
    for (int i = 1; i <= n; i++) {
        for (Dinic::Edge& e : g[i]) {
            if (e.capacity == 0) {
                int to = e.to - n - 1;
                if (to > 0) printf("%d %d\n", i, to);
            }
        }
    }
    return 0;
}