Pagini recente » Cod sursa (job #2793660) | Cod sursa (job #33399) | Cod sursa (job #1727109) | Cod sursa (job #496352) | Cod sursa (job #2962154)
#include <iostream>
#include <fstream>
#include <vector>
#include <cmath>
#include <iomanip>
#include <climits>
#include <queue>
using namespace std;
ifstream fin ("cuplaj.in");
ofstream fout ("cuplaj.out");
int n, m1, m2, m;
vector<vector<int>> lista_adiacenta; //lista de adiacenta a grafului
vector<vector<int>> graf_rezid; //pentru a retine capacitatea folosita intr-un anumit moment pentru o muchie
vector<int> vizit;
vector<int> tata;
bool BFS()
{
queue<int> vecini;
tata.clear();
tata.resize(n+1, 0);
vizit.clear();
vizit.resize(n+1, 0);
vecini.push(1);
vizit[1] = 1;
while(!vecini.empty()){
int nod_curent = vecini.front();
vecini.pop();
if (nod_curent == n) break; //am ajuns la final
for (auto it: lista_adiacenta[nod_curent]){
if (!vizit[it] and graf_rezid[nod_curent][it] > 0){ //daca nu am trecut prin acel nod si capacitatea sa imi permite sa trec, atunci ma duc
tata[it] = nod_curent; //ca sa retin drumul facut
vecini.push(it);
vizit[it] = 1;
}
}
}
return vizit[n]; //vizit[n] va fi true doar daca pot ajunge de la nodul 1 la nodul n
}
void DFS(int nod_inceput, vector<bool> &visited)
{
visited[nod_inceput] = 1;
for (auto it: graf_rezid[nod_inceput]){
if (graf_rezid[nod_inceput][it] and !visited[it])
DFS(it, visited);
}
}
void getNrCuplaj()
{
int nr = 0;
for (int i = 1; i <= m1; i++){
if (!graf_rezid[1][i * 2]) nr++;
}
fout << nr << endl;
}
int findVecin(int nod)
{
for (int i = 1; i <= m2; i++){
if (!graf_rezid[nod][i * 2 + 1]) return i;
}
}
void findCuplaj()
{
getNrCuplaj();
for (int i = 1; i <= m1; i++){
if (!graf_rezid[1][i * 2]){
int vecin = findVecin(i * 2);
fout << i << " " << vecin << endl;
}
}
}
void EdmondsKarp()
{
int flux_max = 0;
while (BFS()){ //cat timp am drum de la sursa pana la final
for (auto it: lista_adiacenta[n]){ //iau vecinii nodului final
if (vizit[it] and graf_rezid[it][n] > 0){
int flux_curent = graf_rezid[it][n]; ///pornesc cu fluxul egal cu capacitatea vecinului lui n
for (int i = it; i != 1; i = tata[i]){ ///parcurg drumul spre nodul 1
flux_curent = min(flux_curent, graf_rezid[tata[i]][i]); //actualizez fluxul in functie de capacitatea nodurilor pe care le intalnesc in drumul meu
}
//actualizez graful rezidual
graf_rezid[it][n] -= flux_curent;
graf_rezid[n][it] += flux_curent;
for (int i = it; i != 1; i = tata[i]){
graf_rezid[tata[i]][i] -= flux_curent;
graf_rezid[i][tata[i]] += flux_curent;
}
//adaug fluxul curent la cel maxim
flux_max += flux_curent;
}
}
}
findCuplaj();
}
int main()
{
fin >> m1 >> m2 >> m;
//stabilesc nodul final
if (m1 > m2) n = m1 * 2 + 1;
else n = m2 * 2 + 2;
lista_adiacenta.resize(n+1);
graf_rezid.resize(n+1, vector<int>(n+1, -1));
for (int i = 1; i <= m; i++){
int x, y, z;
fin >> x >> y;
//reprezint nodurile din prima multime ca fiind noduri pare in reteaua de transport asociata
//reprezint nodurile din a doua multime ca fiind noduri impare in reteaua de transport asociata
x *= 2;
y = y * 2 + 1;
lista_adiacenta[x].push_back(y);
lista_adiacenta[y].push_back(x); //pentru arcele inverse
graf_rezid[x][y] = 1; //retin capacitatea
}
//adaug arcele de la nodul sursa la fiecare din nodurile din prima multime
for (int i = 1; i <= m1; i++){
lista_adiacenta[1].push_back(i * 2);
lista_adiacenta[i * 2].push_back(1);
graf_rezid[1][i * 2] = 1;
}
//adaug arcele de la nodurile din a doua multime la nodul final
for (int i = 1; i <= m2; i++){
lista_adiacenta[i * 2 + 1].push_back(n);
lista_adiacenta[n].push_back(i * 2 + 1);
graf_rezid[i * 2 + 1][n] = 1;
}
EdmondsKarp();
}