Pagini recente » Cod sursa (job #808950) | Cod sursa (job #1989873) | Cod sursa (job #1574699) | Cod sursa (job #2754996) | Cod sursa (job #2960515)
#include <iostream>
#include <fstream>
#include <vector>
#include <queue>
#include <algorithm>
#include <string>
using namespace std;
ifstream f("cuplaj.in");
ofstream g("cuplaj.out");
vector<vector<int>> graf;
vector<int> vizitat;
vector<int> tata;
vector<vector<int>> capacitate;
vector<vector<int>> flux;
int n, m, sursa, dest, l, r;
void bfs(){
fill(vizitat.begin(), vizitat.end(), 0);
queue<int> coada;
coada.push(sursa);
vizitat[sursa] = 1;
while(!coada.empty()){
int nod = coada.front();
coada.pop();
if(nod == dest)
continue;
for(auto &vecin:graf[nod]){
if(capacitate[nod][vecin] == flux[nod][vecin] || vizitat[vecin] == 1)
continue;
vizitat[vecin] = 1;
tata[vecin] = nod;
coada.push(vecin);
}
}
}
int fluxMaxim(){
int maxFlux = 0;
//facem bfs cat timp mai exista drumuri de la sursa la destinatie pe care sa le verificam pentru fluxul maxim
bfs();
//cout<<"dupa bfs";
while(vizitat[dest] == 1){
//daca am ajuns la destinatie, inseamna ca am gasit un nou drum si verificam fluxul maxim pe acest drum
for(auto vecin: graf[dest]){
if(capacitate[vecin][dest] == flux[vecin][dest]) //daca nu mai am capacitate pe muchia respectiva, nu o mai verific
continue;
tata[dest] = vecin;
//memoram cat mai putem sa adaugam pe acest drum
//sunt sanse ca din cauza ordinei in care am luat drumurile, unul din drumuri sa nu ajunga la capacitatea maxima, fiind
//blocat de un alt drum
int minim = capacitate[tata[dest]][dest] - flux[tata[dest]][dest];
vecin = tata[dest];
while(vecin != sursa){
minim = min(capacitate[tata[vecin]][vecin] - flux[tata[vecin]][vecin], minim);
vecin = tata[vecin];
}
//la final avem in minim cat mai putem sa adaugam pe acest drum
vecin = dest;
while(vecin != sursa){
//adaugam
flux[tata[vecin]][vecin] += minim;
flux[vecin][tata[vecin]] -= minim;
vecin = tata[vecin];
}
maxFlux += minim;
}
bfs();
//cout<<"dupa alt bfs\n";
//cout<<maxFlux;
//cout<<"\n";
}
return maxFlux;
}
int main() {
f>>l>>r>>m;
n = l + r;
sursa = 1;
dest = n + 2;
graf.resize(n + 3);
vizitat.resize(n+3);
tata.resize(n+3); //tata[i] = nodul din care am ajuns in nodul i
capacitate.resize(n+3, vector<int>(n+3)); //capacitatea maxima a muchiei (i,j)
flux.resize(n+3, vector<int>(n+3)); //fluxul propriu-zis de la i la j
for(int i = 1; i <= m; i++){
int x, y;
f>>x>>y;
graf[x + 1].push_back(y + l + 1);
graf[y + l + 1].push_back(x + 1);
capacitate[x + 1][y + l + 1] = 1;
}
//adaugam un nod sursa care va fi nodul 1 si un nod destinatie care va fi nodul n+2
//facem muchii de la sursa la fiecare nod din stanga si de la fiecare nod din dreapta la destinatie
//capacitatea maxima a acestor muchii va fi 1
//reducem problema determinarii unui cuplaj maxim intr un graf bipartit la problema
//determinarii unui flux maxim intr-o retea de transport asociata acelui graf bipartit si cu adaugarea
//nodurilor sursa si destinatie
for(int i = 2; i <= l + 1; i++){
graf[sursa].push_back(i);
graf[i].push_back(sursa);
capacitate[sursa][i] = 1;
}
for(int i = l + 2; i <= n + 1; i++){
graf[i].push_back(dest);
graf[dest].push_back(i);
capacitate[i][dest] = 1;
}
//afisare matrice de capacitate
// for(int i = 1; i <= dest; i++){
// for(int j = 1; j <= dest; j++){
// cout<<capacitate[i][j]<<" ";
// }
// cout<<endl;
// }
g<<fluxMaxim()<<"\n";
//nodurile cuplate vor reprezenta arcele cu flux nenul care nu sunt incidente nici cu sursa nici cu destinatia
//adaugam aceste arce la multimea de arce care formeaza cuplajul maxim si le afisam
vector<pair<int, int>> cuplaj;
for(int i = 2; i <= l + 1; i++){
for(auto vecin: graf[i]){
if(vecin != sursa && flux[i][vecin] == 1){
cuplaj.push_back({i - 1, vecin - l - 1});
}
}
}
for(auto &pereche: cuplaj){
g<<pereche.first<<" "<<pereche.second<<endl;
}
return 0;
}