Cod sursa(job #2961913)

Utilizator crivoicarlaCrivoi Carla crivoicarla Data 7 ianuarie 2023 13:23:24
Problema Cuplaj maxim in graf bipartit Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.83 kb
//
// Created by Carla on 1/7/2023.
//
#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;
}