Cod sursa(job #3140345)

Utilizator PostoacaMateiMatei Postoaca PostoacaMatei Data 5 iulie 2023 16:36:43
Problema Cuplaj maxim in graf bipartit Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.29 kb
#include <iostream>
#include <fstream>
#include <vector>
#include <queue>

using namespace std;

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

vector<int> gf[100001];
int n, m, e, pairst[100001], pairdr[100001], dist[100001];
const int inf = 2e9;
const int NIL = 0;

bool bfs() {
    // returneaza true daca exista un lant augmentat valabil
    queue<int> q;
    // facem aici doar primul nivel de noduri
    for (int st = 1; st <= n; st++)
        if (pairst[st] == NIL) {
            // daca este un nod liber, atunci il adaugam la coada
            dist[st] = 0; // st nu este cuplat asadar distanta este 0
            q.push(st);
        }
        else
            dist[st] = inf; // va fi considerat data viitoare pentru valabilitate
    dist[NIL] = inf;
    // q va contine numai noduri de la stanga
    while (!q.empty()) {
        int st = q.front();
        q.pop();
        // daca nodul st este diferit de NIL si poate oferi un lant mai scurt spre NIL, atunci:
        if (dist[st] < dist[NIL])
            for (int dr : gf[st])
                if (dist[pairdr[dr]] == inf) {// daca perechea lui dr nu a mai fost considerata, adica
                    //                           muchia {dr, pairdr[dr]} nu a fost explorata
                    // acum vom considera perechia si o vom pune in coada
                    dist[pairdr[dr]] = dist[st] + 1;
                    q.push(pairdr[dr]);
                }
    }
    // daca am reusit sa ne intoarcem la NIL cu un lant alternativ format din noduri distincte,
    // asta inseamna ca exista un lant alternant valabil
    if (dist[NIL] != inf)
        return true;
    else
        return false;
}

bool dfs(int st) {
    // returneaza ture daca exista un lant augmentat care incepe din nodul liber st
    if (st != NIL) {
        for (int dr : gf[st])
            if (dist[pairdr[dr]] == dist[st] + 1) // urmarim distantele setate de BFS
                if (dfs(pairdr[dr]) == true) { // daca dfs pentru perechea lui dr returneaza true,
                    // atunci am gasit noi cuplaje posibile -> stocam cuplajele in array-uri
                    pairdr[dr] = st;
                    pairst[st] = dr;
                    return true;
                }
        // daca nu exista niciun lant augmentat care incepe din st
        dist[st] = inf;
        return false;
    }
    // st este NIL
    return true;
}

int hopcroft_karp() {
    for (int st = 0; st <= n; st++)
        pairst[st] = NIL;
    for (int dr = 0; dr <= m; dr++)
        pairdr[dr] = NIL;
    int rez = 0; // ceea ce returnam

    while (bfs()) { // cat timp exista un lant augmentat
        for (int st = 1; st <= n; st++) // cautam un nod liber pentru a verifica pentru un cuplaj
            // daca nodul curent este liber si exista un lant augmentat de la nodul curent atunci incrementam
            if (pairst[st] == NIL && dfs(st))
                rez++;
    }
    return rez;
}

int main()
{
    fin >> n >> m >> e;
    for (int i = 1; i <= e; i++) {
        int x, y;
        fin >> x >> y;
        gf[x].push_back(y);
    }
    int rez = hopcroft_karp();
    fout << rez << "\n";
    for (int st = 1; st <= n; st++)
        if (pairst[st] != 0)
            fout << st << " " << pairst[st] << "\n";
    return 0;
}