Pagini recente » Monitorul de evaluare | Monitorul de evaluare | Monitorul de evaluare | Cod sursa (job #1522699) | Cod sursa (job #3331821)
#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;
// }