Cod sursa(job #3042199)

Utilizator ptudortudor P ptudor Data 4 aprilie 2023 18:47:08
Problema Cuplaj maxim in graf bipartit Scor 50
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.84 kb
#include <bits/stdc++.h>
#define int long long
using namespace std;

//#define LOCAL

#ifdef LOCAL
ifstream in("in.in");
ofstream out("out.out");
#else
ifstream in("cuplaj.in");
ofstream out("cuplaj.out");
#endif

const int inf = (1LL << 61);

namespace MaxFlow {
    struct Edge {
        int to,rev,cap,flow;
    };
    vector<Edge> edges;
    vector<vector<int>> g;
    vector<int> parent,dis,parentEdge;
    void init(int n) {
        g.resize(n + 1);
        dis.resize(n + 1);
        parent.resize(n +1);
        parentEdge.resize(n+1);
    }
    void add_edge(int u, int v, int cap) {
        //cout << "add edge " << u << " " << v << "\n";
        g[u].push_back(edges.size());
        edges.push_back(Edge{v,(int)edges.size(),cap,0});
        g[v].push_back(edges.size());
        edges.push_back(Edge{u,(int)edges.size() - 1, 0, 0});
    }

    int dif(const Edge &v) {
        return v.cap - v.flow;
    }

    bool bfs(int s, int t) {
        fill(dis.begin(),dis.end(),inf);
        fill(parent.begin(),parent.end(),-1);
        queue<int> q;
        dis[s] = 0;
        q.push(s);
        while(!q.empty()) {
            int node = q.front();
            q.pop();
            for (auto e : g[node]) {
                int to = edges[e].to;
                if (dis[node] + 1 < dis[to] && dif(edges[e])) {
                    dis[to] = dis[node] + 1;
                    parent[to] = node;
                    parentEdge[to] = e;///the edge that got us here
                    q.push(to);
                }
            }
        }
        return (parent[t] != -1);
    }
    int get_flow(int s, int t) {
        int total_flow = 0;
        while(bfs(s,t)) {
            int node = t,bottle_neck = inf;
            while(parent[node] != -1) {
                int from = parent[node];
                bottle_neck = min(bottle_neck, dif(edges[parentEdge[node]]));
                node = from;
            }

            node = t;
            while(parent[node] != -1) {
                int from = parent[node];
                edges[parentEdge[node]].flow += bottle_neck;
                edges[parentEdge[node]^1].flow -= bottle_neck;
                node = from;
            }

            total_flow += bottle_neck;
        }
        return total_flow;
    }
}

int n,m,e;
int32_t main() {
    in >> n  >> m >> e;
    MaxFlow::init(n + m + 1);
    for (int i = 1; i <= n; i++) {
        MaxFlow::add_edge(0,i,1);
    }
    for (int i = 1; i <=m; i++) {
        MaxFlow::add_edge(i + n, n + m + 1,1);
    }
    for (int i = 1; i <= e; i++) {
        int u,v;
        in >> u >> v;
        MaxFlow::add_edge(u,v + n,1);
    }
    
    out << MaxFlow::get_flow(0,n+m+1) << "\n";
    for  (int i = 1; i <= n; i++) {
        for (auto k : MaxFlow::g[i]) {
            if (MaxFlow::edges[k].flow > 0) {
                out << i << " " << -n + MaxFlow::edges[k].to << "\n";
            }
        }
    }
}