Cod sursa(job #3328585)

Utilizator h4rap-a1bMihail Cosor h4rap-a1b Data 9 decembrie 2025 12:58:00
Problema Cuplaj maxim in graf bipartit Scor 50
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.11 kb
//
// Created by h4rapa1b on 12/9/25.
//

#include <algorithm>
#include <fstream>
#include <queue>
#include <vector>

using namespace std;

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

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

vector<edge> grafic[NMAX];
int parent[NMAX];
int parentIndex[NMAX];

int bfs(int s, int d) {
    // reset vector de parinti
    for (int i = 0; i < NMAX; ++i) {
        parent[i] = -1;
    }

    queue<int> q;
    q.push(s);
    parent[s] = -2; // sursa vizitata

    while (!q.empty()) {
        int nod = q.front();
        q.pop();

        if (nod == d) break; // am gasit destinatia

        for (int i = 0; i < grafic[nod].size(); ++i) {
            edge &e = grafic[nod][i];
            // daca nodul nu a fost vizitat si mai exista capacitate reziduala disponibila
            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; // nu mai exista drum de augmentare
    }

    // determinam fluxul minim pe drumul gasit
    int flow = INF;
    int curr = d;
    while (curr != s) {
        int prev = parent[curr];
        int edgeIndex = parentIndex[curr];
        // actualizam fluxul minim
        flow = min(flow, grafic[prev][edgeIndex].cap - grafic[prev][edgeIndex].flow);
        curr = prev;
    }

    curr = d;
    while (curr != s) {
        int prev = parent[curr];
        int edgeIndex = parentIndex[curr];

        // adaugam flux pe muchia directa
        grafic[prev][edgeIndex].flow += flow;

        // scadem flux pe muchia inversa
        int revIndex = grafic[prev][edgeIndex].rev;
        grafic[curr][revIndex].flow -= flow;

        curr = prev;
    }

    return flow;
}

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

    grafic[from].push_back(forward);
    grafic[to].push_back(backward);
}

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

    int n, m, e;
    fin >> n >> m >> e;

    int sursa = 0;
    int destinatie = n + m + 1;

    // de la sursa catre partea stanga
    for (int i = 1; i <= n; ++i) {
        add_adge(sursa, i, 1);
    }

    // de la dreapta la destinatie
    for (int i = 1; i <= m; ++i) {
        add_adge(i + n, destinatie, 1);
    }

    // muchiile din graf
    for (int i = 0; i < e; ++i) {
        int u, v;
        fin >> u >> v;
        add_adge(u, v + n, 1);
    }

    int maxFlow = 0;
    while (true) {
        int flow = bfs(sursa, destinatie);
        if (flow == 0) {
            break; // nu mai exista drumuri de augmentare
        }
        maxFlow += flow;
    }

    fout << maxFlow << "\n";

    // afisarea cuplajului
    for (int u = 1; u <= n; ++u) {
        for (auto &e : grafic[u]) {
            // daca exista flux pe muchie, atunci face parte din cuplaj
            if (e.to != sursa && e.flow > 0) {
                fout << u << " " << e.to - n << "\n";
            }
        }
    }

    fin.close();
    fout.close();
    return 0;
}