Cod sursa(job #3328608)

Utilizator denis_cristeaCristea Denis-Adrian denis_cristea Data 9 decembrie 2025 13:23:25
Problema Cuplaj maxim in graf bipartit Scor 50
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.43 kb
#include <fstream>
#include <vector>
#include <queue>
#include <algorithm>

const int N_MAX = 20005;
const int INF = 1e9;

struct edge {
    int to, rev;
    int cap, flow;
};

std::vector<edge> G[N_MAX];
int parent[N_MAX];
int parentIndex[N_MAX];

int n, m, e;

int bfs(int s, int d) {
    for(int i = 0; i < N_MAX; i++) {
        parent[i] = -1;
    }
    
    std::queue<int> q;
    q.push(s);
    parent[s] = -2;

    while(!q.empty()) {
        int nod = q.front();
        q.pop();
        
        if(nod == d) break;
        
        for (size_t i = 0; i < G[nod].size(); i++) {
            edge &e = G[nod][i];
            if(parent[e.to] == -1 && e.cap > e.flow) {
                parent[e.to] = nod;
                parentIndex[e.to] = i;
                q.push(e.to);
            }
        }
    }

    if(parent[d] == -1) {
        return 0;
    }

    int flow = INF;
    int curr = d;
    while(curr != s) {
        int prev = parent[curr];
        int edgeIndex = parentIndex[curr];
        flow = std::min(flow, G[prev][edgeIndex].cap - G[prev][edgeIndex].flow);
        curr = prev;
    }

    curr = d;
    while(curr != s) {
        int prev = parent[curr];
        int edgeIndex = parentIndex[curr];
        
        G[prev][edgeIndex].flow += flow;
        
        int revIndex = G[prev][edgeIndex].rev;
        G[curr][revIndex].flow -= flow;
        
        curr = prev;
    }

    return flow;
}

void add_edge(int from, int to, int cap) {
    edge forward = {to, (int)G[to].size(), cap, 0};
    edge backward = {from, (int)G[from].size(), 0, 0};
    
    G[from].push_back(forward);
    G[to].push_back(backward);
}

int main() {
    std::ifstream fin("cuplaj.in");
    std::ofstream fout("cuplaj.out");

    fin >> n >> m >> e;
    
    int source = 0;
    int sink = n + m + 1;
    
    for(int i = 1; i <= n; i++) {
        add_edge(source, i, 1);
    }
    
    for(int i = 1; i <= m; i++) {
        add_edge(n + i, sink, 1);
    }
    
    for(int i = 0; i < e; i++) {
        int u, v;
        fin >> u >> v;
        add_edge(u, n + v, 1);
    }
    
    int maxflow = 0;
    while (true) {
        int flow = bfs(source, sink);
        if(flow == 0) {
            break;
        }
        maxflow += flow;
    }
    
    fout << maxflow << '\n';
    
    for(int u = 1; u <= n; u++) {
        for (auto &e : G[u]) {
            if(e.to != source && e.flow > 0) {
                fout << u << ' ' << e.to - n << '\n';
            }
        }
    }
}