Pagini recente » Cod sursa (job #3136416) | Cod sursa (job #380625) | Cod sursa (job #368826) | Cod sursa (job #226266) | Cod sursa (job #2967904)
//Complexitate: O(n * m^2)
#include <bits/stdc++.h>
using namespace std;
ifstream fin("cuplaj.in");
ofstream fout("cuplaj.out");
long long int capGrafRezidual[10000][10000], tata[10000];
vector<vector<int> > listaAdiacenta;
int newSource, newDestination;
int N, M, E;
bool bfs() {
vector<bool> vizitat;
queue<int> q;
vizitat.resize(newDestination + 1);
q.push(newSource);
vizitat[newSource] = true;
while(!q.empty()){
int nod = q.front();
q.pop();
for(auto vecin : listaAdiacenta[nod]){
// Daca vecinul nu e vizitat si se poate adauga flow pe muchia de la nod la el (capacitatea e mai mare decat 0)
if(!vizitat[vecin] && capGrafRezidual[nod][vecin]){
// Este updatat vectorul tata pentru a putea reconstrui drumul de ameliorare
tata[vecin] = nod;
vizitat[vecin] = true;
q.push(vecin);
// Daca vecinul este destinatia atunci am gasit un drum bun
// BFS-ul este optimizat pentru ca el se incide direct cand vecinul este destinatia
if(vecin == newDestination)
return true;
}
}
}
return false;
}
int edmondsKarp()
{
int raspuns = 0;
// Cat timp mai gasesc un drum pana la destinatie pe care pot adauga flow
while(bfs()) {
int nod = newDestination, bottleNeck = 1000000000;
while(nod != newSource) {
int parinte = tata[nod];
if(capGrafRezidual[parinte][nod] < bottleNeck) {
// Este calculata valoarea minima de pe drumul respectiv (bottleNeck), de la destinatie la sursa
// folosind vectorul tata
bottleNeck = capGrafRezidual[parinte][nod];
}
nod = parinte;
}
// Adaug la toate muchiile de pe drum flow-ul maxim
nod = newDestination;
while(nod != newSource) {
int parinte = tata[nod];
capGrafRezidual[parinte][nod] -= bottleNeck; // Drum direct in graful rezidual
capGrafRezidual[nod][parinte] += bottleNeck; // Drum invers in graful rezidual
nod = parinte;
}
// Adaug flow-ul gasit la raspuns
raspuns += bottleNeck;
}
return raspuns;
}
int main()
{
fin >> N >> M >> E;
listaAdiacenta.assign(N + M + 2, vector<int>());
while(E--) {
int x, y;
fin >> x >> y;
y = N + y;
listaAdiacenta[x].push_back(y);
listaAdiacenta[y].push_back(x);
capGrafRezidual[x][y] = 1;
}
newSource = 0;
newDestination = N + M + 1;
// Adaug muchii de la newSource la fiecare nod din partea stanga
for(int i = 1; i <= N; i++) {
listaAdiacenta[0].push_back(i);
// listaAdiacenta[i].push_back(0);
capGrafRezidual[0][i] = 1;
}
// Adaug muchii de la fiecare nod din partea dreapta la newDestination
for(int i = N + 1; i <= N + M; i++) {
listaAdiacenta[i].push_back(newDestination);
// listaAdiacenta[newDestination].push_back(i);
capGrafRezidual[i][newDestination] = 1;
}
fin.close();
fout << edmondsKarp()<< endl;
for(int i = 1; i <= N; i++) {
for(int j = N + 1; j <= N + M; j++) {
if(capGrafRezidual[j][i] == 1) {
// Din teorie, rezultatul este reprezentat de muchiile intermediare unde am flow
fout << i << " " << j - N << endl;
}
}
}
fout.close();
return 0;
}