Cod sursa(job #2889360)

Utilizator andrei_C1Andrei Chertes andrei_C1 Data 12 aprilie 2022 17:50:11
Problema Cuplaj maxim in graf bipartit Scor 80
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 5.75 kb
// #include <bits/stdc++.h>
#include <stdio.h>
#include <vector>
#include <queue>
#include <algorithm>

using namespace std;

class InParser {
private :
    FILE* fin;
    char* buf;
    const int lim = 1 << 18;
    int pos;
    inline void next() {
        if(!(pos = (pos + 1) & (lim - 1))){
            fread(buf, 1, lim, stdin);
        }
    }
public :
    InParser (const char *file){
        fin = freopen(file, "r", stdin);
        pos = lim - 1;
        buf = new char[lim]();
    }
    InParser& operator >> (char &x){
        fscanf(fin, "%c", &x);
        return *this;
    }
    InParser& operator >> (long long &x){
        x = 0;
        int sgn = 1;
        for(; buf[pos] < '0' || buf[pos] > '9'; next()){
            if(buf[pos]=='-'){
                sgn = -1;
            }
        }
        for(; buf[pos] >= '0' && buf[pos] <= '9'; next()){
            x = x * 10 + buf[pos] - '0';
        }
        x *= sgn;
        return *this;
    }
    InParser& operator >> (int &x){
        x = 0;
        int sgn = 1;
        for(; buf[pos] < '0' || buf[pos] > '9'; next()){
            if(buf[pos]=='-'){
                sgn = -1;
            }
        }
        for(; buf[pos] >= '0' && buf[pos] <= '9'; next()){
            x = x * 10 + buf[pos] - '0';
        }
        x *= sgn;
        return *this;
    }
};

class OutParser {
private:
    FILE *fout;
    char *buf;
    int pos;
    const int lim = 1 << 18;
    void write_ch(char ch) {
        if (pos == lim) {
            fwrite(buf, 1, lim, fout);
            pos = 0;
            buf[pos++] = ch;
        } else {
            buf[pos++] = ch;
        }
    }
public:
    OutParser(const char* file) {
        fout = freopen(file, "w", stdout);
        buf = new char[lim]();
        pos = 0;
    }
    ~OutParser() {
        fwrite(buf, 1, pos, fout);
        fclose(fout);
    }
    OutParser& operator << (int x) {
        if(x < 0) {
            write_ch('-');
            x = -x;
        }
        if (x <= 9) {
            write_ch(x + '0');
        } else {
            (*this) << (x / 10);
            write_ch(x % 10 + '0');
        }
        return *this;
    }
    OutParser& operator << (long long x) {
        if(x < 0) {
            write_ch('-');
            x = -x;
        }
        if (x <= 9) {
            write_ch(x + '0');
        } else {
            (*this) << (x / 10);
            write_ch(x % 10 + '0');
        }
        return *this;
    }
    OutParser& operator << (char x) {
        write_ch(x);
        return *this;
    }
    OutParser& operator << (const char *x) {
        while (*x) {
            write_ch(*x);
            ++x;
        }
        return *this;
    }
};

InParser fin("cuplaj.in");
OutParser fout("cuplaj.out");

const int INF = 1e9;
const int NMAX = 20000;

int N, M, E, ans, s, d;

struct FlowEdge {
    int v, u;
    long long cap, flow = 0;
    FlowEdge(int v, int u, long long cap) : v(v), u(u), cap(cap) {}
};

struct Dinic {
    const long long flow_inf = 1e18;
    vector<FlowEdge> edges;
    vector<vector<int>> adj;
    int n, m = 0;
    int s, t;
    vector<int> level, ptr;
    queue<int> q;

    Dinic(int n, int s, int t) : n(n), s(s), t(t) {
        adj.resize(n);
        level.resize(n);
        ptr.resize(n);
    }

    void add_edge(int v, int u, long long cap) {
        edges.emplace_back(v, u, cap);
        edges.emplace_back(u, v, 0);
        adj[v].push_back(m);
        adj[u].push_back(m + 1);
        m += 2;
    }

    bool bfs() {
        fill(level.begin(), level.end(), -1);
        level[s] = 0;
        q.push(s);
        while (!q.empty()) {
            int v = q.front();
            q.pop();
            for (int id : adj[v]) {
                if (edges[id].cap - edges[id].flow < 1)
                    continue;
                if (level[edges[id].u] != -1)
                    continue;
                level[edges[id].u] = level[v] + 1;
                q.push(edges[id].u);
            }
        }
        return level[t] != -1;
    }

    long long dfs(int v, long long pushed) {
        if (pushed == 0)
            return 0;
        if (v == t)
            return pushed;
        for (int& cid = ptr[v]; cid < (int)adj[v].size(); cid++) {
            int id = adj[v][cid];
            int u = edges[id].u;
            if (level[v] + 1 != level[u] || edges[id].cap - edges[id].flow < 1)
                continue;
            long long tr = dfs(u, min(pushed, edges[id].cap - edges[id].flow));
            if (tr == 0)
                continue;
            edges[id].flow += tr;
            edges[id ^ 1].flow -= tr;
            return tr;
        }
        return 0;
    }

    long long flow() {
        long long f = 0;
        while (bfs()) {
            fill(ptr.begin(), ptr.end(), 0);
            while (long long pushed = dfs(s, flow_inf)) {
                f += pushed;
            }
        }
        return f;
    }
};

int main() {
    fin >> N >> M >> E;

    s = 0;
    d = N + M + 1;

    Dinic solver(N + M + 2, s, d);

    for(int i = 1; i <= E; i++) {
        int u, v;
        fin >> v >> u;

        u += N;

        solver.add_edge(v, u, 1);
    }

    for(int node = 1; node <= N; node++) {
        solver.add_edge(s, node, 1);
    }

    for(int node = N + 1; node <= N + M; node++) {
        solver.add_edge(node, d, 1);
    }

    fout << solver.flow() << '\n';

    for(auto it: solver.edges) {
        if(it.cap == 0) {
            continue;
        }

        if(it.v == s || it.u == d) {
            continue;
        }

        if(it.flow == it.cap) {
            fout << it.v << " " << it.u - N << '\n';
        }
    }
    return 0;
}