Cod sursa(job #3331820)

Utilizator GliggyGligor Andrei Gliggy Data 31 decembrie 2025 15:36:11
Problema Cuplaj maxim in graf bipartit Scor 60
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 7.04 kb
// #include <iostream>    // Librăria pentru fluxurile standard de intrare/ieșire
// #include <vector>      // Librăria pentru vectori (liste dinamice)
// #include <queue>       // Librăria pentru structura de date de tip coadă (folosită la BFS)
// #include <fstream>     // Librăria pentru lucrul cu fișiere

// using namespace std;   // Permite utilizarea funcțiilor standard fără prefixul std::

// const int MAXN = 10005; // Definim dimensiunea maximă pentru noduri conform restricțiilor
// const int INF = 1e9;    // Definim o valoare foarte mare pentru distanțe (infinit)

// ifstream fin("cuplaj.in");   // Deschidem fișierul de intrare
// ofstream fout("cuplaj.out"); // Deschidem fișierul de ieșire

// vector<int> adj[MAXN];      // Lista de adiacență pentru a stoca muchiile dintre mulțimile A și B
// int perecheA[MAXN];         // perecheA[u] stochează nodul din B cu care este cuplat u din A
// int perecheB[MAXN];         // perecheB[v] stochează nodul din A cu care este cuplat v din B
// int dist[MAXN];             // Stochează nivelul (stratul) fiecărui nod calculat de BFS
// int n, m, e;                // n - noduri în A, m - noduri în B, e - numărul de muchii

// // Funcția BFS: Împarte graful în straturi pentru a găsi cele mai scurte drumuri de creștere
// bool bfs() {
//     queue<int> q;           // Creăm o coadă pentru parcurgerea în lățime
//     for (int i = 1; i <= n; i++) { // Parcurgem toate nodurile din mulțimea A
//         if (perecheA[i] == 0) {    // Dacă nodul i este liber (necuplat)
//             dist[i] = 0;           // Începe un nou drum de creștere (nivelul 0)
//             q.push(i);             // Îl adăugăm în coadă pentru procesare
//         } else {
//             dist[i] = INF;         // Dacă e deja cuplat, îl marcam cu infinit (nevizitat)
//         }
//     }

//     dist[0] = INF; // Nodul 0 este un nod virtual care reprezintă "capătul" unui drum de creștere

//     while (!q.empty()) {           // Cât timp mai avem noduri în coadă
//         int u = q.front();         // Luăm primul nod din coadă
//         q.pop();                   // Îl eliminăm din coadă

//         if (dist[u] < dist[0]) {   // Dacă nu am depășit nivelul primului drum de creștere găsit
//             for (int v : adj[u]) { // Analizăm toți vecinii nodului u din mulțimea B
//                 // Verificăm dacă partenerul lui v (care e în A) nu a fost vizitat
//                 if (dist[perecheB[v]] == INF) {
//                     dist[perecheB[v]] = dist[u] + 1; // Setăm stratul următor
//                     q.push(perecheB[v]);             // Adăugăm partenerul în coadă
//                 }
//             }
//         }
//     }
    
//     // Returnează true dacă am reușit să ajungem la nodul virtual 0 (un nod liber din B)
//     return (dist[0] != INF);
// }

// // Funcția DFS: Caută drumuri de creștere pe straturile definite de BFS
// bool dfs(int u) {
//     if (u != 0) { // Dacă nodul curent nu este nodul virtual de final
//         for (int v : adj[u]) { // Parcurgem vecinii nodului u
//             // Verificăm dacă vecinul face parte din stratul imediat următor
//             if (dist[perecheB[v]] == dist[u] + 1) {
//                 if (dfs(perecheB[v])) { // Încercăm să găsim un drum de creștere recursiv
//                     perecheB[v] = u;    // Dacă s-a găsit, actualizăm cuplajul pentru v
//                     perecheA[u] = v;    // Actualizăm cuplajul pentru u
//                     return true;        // Confirmăm că drumul a fost găsit
//                 }
//             }
//         }
//         dist[u] = INF; // Dacă nu există drum prin u, îl marcăm pentru a nu-l mai vizita
//         return false;  // Nu am găsit drum de creștere prin acest nod
//     }
//     return true; // Am ajuns la nodul virtual 0, drumul de creștere este complet
// }

// int main() {
//     if (!(fin >> n >> m >> e)) return 0; // Citim dimensiunile și verificăm dacă s-a reușit

//     for (int i = 0; i < e; i++) { // Citim cele e muchii ale grafului
//         int u, v;                 // Variabile pentru nodurile ce formează muchia
//         fin >> u >> v;            // Citim nodul u din A și nodul v din B
//         adj[u].push_back(v);      // Adăugăm v în lista de adiacență a lui u
//     }

//     int cuplaj_maxim = 0;         // Variabilă pentru a număra câte perechi am format
    
//     // Rulăm algoritmul în faze: BFS construiește straturi, DFS caută drumuri în ele
//     while (bfs()) {               // Cât timp BFS găsește drumuri de creștere posibile
//         for (int i = 1; i <= n; i++) { // Pentru fiecare nod din mulțimea A
//             // Dacă nodul este liber și DFS reușește să îi găsească o pereche
//             if (perecheA[i] == 0 && dfs(i)) {
//                 cuplaj_maxim++;   // Incrementăm mărimea totală a cuplajului
//             }
//         }
//     }

//     fout << cuplaj_maxim << "\n"; // Afișăm numărul maxim de perechi formate
//     for (int i = 1; i <= n; i++) { // Parcurgem nodurile din prima mulțime
//         if (perecheA[i] != 0) {    // Dacă nodul i a fost cuplat
//             fout << i << " " << perecheA[i] << "\n"; // Afișăm perechea (A, B)
//         }
//     }

//     return 0; // Finalizăm programul
// }
// Copilot Rules:
// RULE: There shouldnt be any spaces in the code, except after commas.
// RULE: All variables in main should be declared globally, and can be used before they are defined.
// RULE: All open curly braces should be placed on the same line as the function or control structure they belong to, not on the line after.
#include <bits/stdc++.h>
#define N 10010
using namespace std;
ifstream fin("cuplaj.in");   //strudel
ofstream fout("cuplaj.out"); //cuplaj
int n,m,e,i,x,y,cnt,inf=1e9;
vector<int> v[N];
int pda[N],pdb[N],lvl[N];
queue<int> q;
bool bfs(){
    while(!q.empty()) q.pop();
    for(i=1;i<=n;i++){
        if(pdb[i]==0) lvl[i]=0,q.push(i);
        else lvl[i]=inf;
    }
    lvl[0]=inf;
    while(!q.empty()){
        int u=q.front();
        q.pop();
        if(lvl[u]<lvl[0])
            for(auto vec:v[u]){
                if(lvl[pda[vec]]==inf){
                    lvl[pda[vec]]=lvl[u]+1;
                    q.push(pda[vec]);
                }
            }
    }
    return lvl[0]!=inf;
}
bool dfs(int nod){
    if(nod==0) return 1;
    for(auto vec:v[nod]){
        if(lvl[pda[vec]]==lvl[nod]+1&&dfs(pda[vec])==1){
            pda[vec]=nod,pdb[nod]=vec;
            return 1;
        }
    }
    lvl[nod]=inf;
    return 0;
}
int main()
{
    fin>>n>>m>>e;
    for(i=1;i<=e;i++){
        fin>>x>>y;
        v[x].push_back(y);
    }
    while(bfs()==1){
        for(i=1;i<=n;i++){
            if(pdb[i]==0&&dfs(i)==1){
                cnt++;
                break;
            }
        }
    }
    fout<<cnt<<'\n';
    for(i=1;i<=n;i++)
        if(pdb[i]!=0) fout<<i<<" "<<pdb[i]<<'\n';
    return 0;
}