Cod sursa(job #1867413)

Utilizator msciSergiu Marin msci Data 4 februarie 2017 02:03:31
Problema Cuplaj maxim in graf bipartit Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 4.07 kb
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <string>
#include <sstream>
#include <algorithm>
#include <vector>
#include <queue>
#include <deque>
#include <set>
#include <map>
#include <unordered_map>
#include <unordered_set>
#include <random>
#include <tuple>
#include <limits>
#include <functional>
#include <complex>
#include <bitset>
#include <list>

//#include <atomic>
//#include <condition_variable>
//#include <future>
//#include <mutex>
//#include <thread>

using namespace std;

#define debug(x) cerr << #x << " = " << x << "\n"

const int INF           = 0x3f3f3f3f;
const long long INFL    = 0x3f3f3f3f3f3f3f3fLL;

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;
    }
};

const int Dinic::InfCapacity;

int main(int argc, char* argv[]) 
{
    freopen("cuplaj.in", "r", stdin);
    freopen("cuplaj.out", "w", stdout);
    cin.sync_with_stdio(false);
    int l, r, n;
    cin >> l >> r >> n;
    int s = 0, t = l + r + 1;
    Dinic mf; mf.init(l + r + 2);
    for (int i = 1; i <= l; i++) mf.add(s, i, 1);
    for (int i = l + 1; i <= l + r; i++) mf.add(i, t, 1);
    for (int i = 0; i < n; i++)
    {
        int x, y;
        cin >> x >> y;
        mf.add(x, l + y, 1);
    }
    const vector< vector<Dinic::Edge> >& g = mf.g;
    cout << mf.maximum_flow(s, t) << "\n";
    for (int i = 1; i <= l; i++)
    {
        for (const Dinic::Edge& e : g[i])
        {
            if (e.capacity == 0 && e.to - l > 0)
            {
                cout << i << " " << e.to - l << "\n";
                break;
            }
        }
    }
    return 0;
}