Cod sursa(job #2961045)

Utilizator Rincu_StefaniaRincu Stefania Rincu_Stefania Data 5 ianuarie 2023 16:56:03
Problema Cuplaj maxim in graf bipartit Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.8 kb
#include <iostream>
#include <vector>
#include <queue>
#include <algorithm>
#include <cstring>
#include <fstream>

using namespace std;

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

///l -> vect de adiacenta
vector<int> l[20001];
///viz -> vector de vizitate
///stim ca problemele de cuplaj se rezolva pe un graf bipartit deci vom avea 2 vectori: gr1 -> partitia din stanga si gr2 -> partitia din dreapta
int viz[20001], gr1[20001], gr2[20001] ;

///functia care realizeaza cuplajul celor doua partitii
int matching(int val)
{
    ///daca nodul nu e vizitat mergem mai departe
    if(viz[val])
        return 0;
    ///marchez nodul ca vizitat
    viz[val] = 1;
    ///iterez prin lista de adiacenta a acestuia si caut un vecin din a doua partitie care nu are pereche si ii adaug reciproc pe fiecare
    ///vectorul celeilalte persoane, iar daca gasesc o astfel de pereche pe care reusesc sa o cuplez intrerup functia => succes
    for(int i = 0; i < l[val].size(); i++)
        if(!gr2[l[val][i]])
        {
            gr1[val] = l[val][i];
            gr2[l[val][i]] = val;
            return 1;
        }
    ///daca am trecut de comanda anterioara fara sa mai gasesc persoane necuplate pt valoarea mea, atunci ma uit daca pot cupla persoanele
    ///din cealalta partitie cu alte persoane, daca gasesc ies din functie => succes
    for(int i = 0; i < l[val].size(); i++)
        if(matching(gr2[l[val][i]]))
        {
            gr1[val] = l[val][i];
            gr2[l[val][i]] = val;
            return 1;
        }
    ///n-am gasit nimic, nu sunt petitor bun => esec(nu mai pot cupla persoane)
    return 0;
}

int main()
{
    int n, m, e, st, fin, ok = 1, match = 0;
    ///citim cadinalele celor doua multimi si nr de legaturi dintre ele
    in>>n>>m>>e;
    ///citim legaturile
    ///pentru a avea flux -> legam nodurile doar din stanga in dreapta
    for(int i = 1; i <= e; i++)
    {
        in>>st>>fin;
        l[st].push_back(fin);
    }

    ///cat timp reusim sa efectuam cuplaje parcurgem aceasta bucla while cu ajutorul careia
    ///cautam nodurile care nu au pereche si care mai pot forma o pereche
    while(ok)
    {
        ok = 0;
        ///resetam vectorul de vizitate
        memset(viz, 0, sizeof(viz));
        for(int i = 1; i <= n; i++)
            if(!gr1[i])
                ok |= matching(i);
    }

    ///numaram cate cuplaje s-au format, contorizand cate persoane din prima partitie au pereche
    for(int i = 1; i <= n; i++)
        if(gr1[i])
            match += 1;
    out<<match<<"\n";

    ///afisam perechile cautand persoanele din prima partitie care au pereche si afisand valoarea perechii lor, memorata in vector
    for(int i = 1; i <= n; i++)
        if(gr1[i])
           out<<i<<" "<<gr1[i]<<"\n";
    return 0;
}