Pagini recente » Cod sursa (job #1145447) | Cod sursa (job #331249) | Cod sursa (job #3125849) | Cod sursa (job #1265675) | Cod sursa (job #3140345)
#include <iostream>
#include <fstream>
#include <vector>
#include <queue>
using namespace std;
ifstream fin("cuplaj.in");
ofstream fout("cuplaj.out");
vector<int> gf[100001];
int n, m, e, pairst[100001], pairdr[100001], dist[100001];
const int inf = 2e9;
const int NIL = 0;
bool bfs() {
// returneaza true daca exista un lant augmentat valabil
queue<int> q;
// facem aici doar primul nivel de noduri
for (int st = 1; st <= n; st++)
if (pairst[st] == NIL) {
// daca este un nod liber, atunci il adaugam la coada
dist[st] = 0; // st nu este cuplat asadar distanta este 0
q.push(st);
}
else
dist[st] = inf; // va fi considerat data viitoare pentru valabilitate
dist[NIL] = inf;
// q va contine numai noduri de la stanga
while (!q.empty()) {
int st = q.front();
q.pop();
// daca nodul st este diferit de NIL si poate oferi un lant mai scurt spre NIL, atunci:
if (dist[st] < dist[NIL])
for (int dr : gf[st])
if (dist[pairdr[dr]] == inf) {// daca perechea lui dr nu a mai fost considerata, adica
// muchia {dr, pairdr[dr]} nu a fost explorata
// acum vom considera perechia si o vom pune in coada
dist[pairdr[dr]] = dist[st] + 1;
q.push(pairdr[dr]);
}
}
// daca am reusit sa ne intoarcem la NIL cu un lant alternativ format din noduri distincte,
// asta inseamna ca exista un lant alternant valabil
if (dist[NIL] != inf)
return true;
else
return false;
}
bool dfs(int st) {
// returneaza ture daca exista un lant augmentat care incepe din nodul liber st
if (st != NIL) {
for (int dr : gf[st])
if (dist[pairdr[dr]] == dist[st] + 1) // urmarim distantele setate de BFS
if (dfs(pairdr[dr]) == true) { // daca dfs pentru perechea lui dr returneaza true,
// atunci am gasit noi cuplaje posibile -> stocam cuplajele in array-uri
pairdr[dr] = st;
pairst[st] = dr;
return true;
}
// daca nu exista niciun lant augmentat care incepe din st
dist[st] = inf;
return false;
}
// st este NIL
return true;
}
int hopcroft_karp() {
for (int st = 0; st <= n; st++)
pairst[st] = NIL;
for (int dr = 0; dr <= m; dr++)
pairdr[dr] = NIL;
int rez = 0; // ceea ce returnam
while (bfs()) { // cat timp exista un lant augmentat
for (int st = 1; st <= n; st++) // cautam un nod liber pentru a verifica pentru un cuplaj
// daca nodul curent este liber si exista un lant augmentat de la nodul curent atunci incrementam
if (pairst[st] == NIL && dfs(st))
rez++;
}
return rez;
}
int main()
{
fin >> n >> m >> e;
for (int i = 1; i <= e; i++) {
int x, y;
fin >> x >> y;
gf[x].push_back(y);
}
int rez = hopcroft_karp();
fout << rez << "\n";
for (int st = 1; st <= n; st++)
if (pairst[st] != 0)
fout << st << " " << pairst[st] << "\n";
return 0;
}