Pagini recente » Cod sursa (job #755722) | Cod sursa (job #2339934) | Cod sursa (job #1520439) | Cod sursa (job #2585783) | Cod sursa (job #2963798)
#include <fstream>
#include <vector>
#include <queue>
#include <iostream>
using namespace std;
ifstream fin("cuplaj.in");
ofstream fout("cuplaj.out");
//O(N*M^2)
//n - numarul de noduri
//m - numarul de muchii
int n, m, x, a, b, flow, flux_max;
queue<int> q;
vector<vector<int>> graf;
vector<vector<int>> graf2;
vector<vector<int>> adj;
bool viz[10001];
int parent[10001];
int bfs(){
while(!q.empty())
q.pop();
for(int i = 0; i <= n + m + 1; i++){
parent[i] = 0;
viz[i] = false;
}
//in coada este retinut nodul si capacitatea
q.push(0);
viz[0] = true;
while(!q.empty()){
int nod = q.front();
q.pop();
if(nod == n + m + 1){
return true;
}
//cautam care sunt vecinii nodului curent si vedem daca a fost vizitat
//daca nu vedem care este fluxul minim pana la acel nod si il retinem
//daca am ajuns la destinatie returnam fluxul
for(auto i : adj[nod]){
if(!viz[i] && graf[nod][i] > 0){
parent[i] = nod;
viz[i] = true;
q.push(i);
}
}
}
return 0;
}
int flux_maxim(){
//daca am gasit un path atunci adunam fluxul la total si trecem prin path folosind vectorul de tati ca sa reconstruim graful
flux_max = 0;
while(bfs()){
for(auto i : adj[n + m + 1]){
if(parent[i]){
parent[n + m + 1] = i;
int flux = 1000001, nod_curent = n + m + 1;
while(nod_curent != 0){
flux = min(flux, graf[parent[nod_curent]][nod_curent]);
nod_curent = parent[nod_curent];
}
nod_curent = n + m + 1;
while(nod_curent != 0){
int prev = parent[nod_curent];
graf[nod_curent][prev] += flux;
graf[prev][nod_curent] -= flux;
nod_curent = prev;
}
flux_max += flux;
}
}
}
return flux_max;
}
void dfs(int nod){
viz[nod] = true;
for(int i = 1; i <= n + m; i++){
if(graf[nod][i] && !viz[i]){
dfs(i);
}
}
}
int main(){
fin >> n >> m >> x;
graf = vector<vector<int>>(n + m + 2, vector <int>(n + m + 2, 0));
adj = vector<vector<int>>(n + m + 2);
graf2 = vector<vector<int>>(n + m + 2, vector <int>(n + m + 2, 0));
for(int i = 0; i < x; i ++){
fin >> a >> b;
graf[a][b + n] = 1;
graf2[a][b + n] = 1;
adj[a].push_back(b + n);
adj[b + n].push_back(a);
}
//legam un nod de start de toate nodurile din coloana stanga
for(int i = 1; i <= n; i++){
graf[0][i] = 1;
graf2[0][i] = 1;
adj[0].push_back(i);
adj[i].push_back(0);
}
//legam un nod de final de toate nodurile din coloana dreapta
for(int i = 1; i <= m; i++){
graf[i + n][n + m + 1] = 1;
graf2[i + n][n + m + 1] = 1;
adj[i + n].push_back(n + m + 1);
adj[n + m + 1].push_back(i + n);
}
fout << flux_maxim() << endl;
for(int i = 0; i <= n + m + 1; i++){
viz[i] = false;
}
dfs(0);
//comparam graf-ul vechi cu cel rezultat dupa flux_max
for(int i = 1; i <= n; i++)
for(int j = n + 1; j <= n + m; j++)
if(!graf[i][j] && graf2[i][j])
fout << i << " " << j - n << endl;
}