Pagini recente » Borderou de evaluare (job #1563011) | Cod sursa (job #2075492) | Cod sursa (job #3304070) | Cod sursa (job #2094725) | Cod sursa (job #3328585)
//
// Created by h4rapa1b on 12/9/25.
//
#include <algorithm>
#include <fstream>
#include <queue>
#include <vector>
using namespace std;
const int NMAX = 20005;
const int INF = 1e9;
struct edge {
int to, rev;
int cap, flow;
};
vector<edge> grafic[NMAX];
int parent[NMAX];
int parentIndex[NMAX];
int bfs(int s, int d) {
// reset vector de parinti
for (int i = 0; i < NMAX; ++i) {
parent[i] = -1;
}
queue<int> q;
q.push(s);
parent[s] = -2; // sursa vizitata
while (!q.empty()) {
int nod = q.front();
q.pop();
if (nod == d) break; // am gasit destinatia
for (int i = 0; i < grafic[nod].size(); ++i) {
edge &e = grafic[nod][i];
// daca nodul nu a fost vizitat si mai exista capacitate reziduala disponibila
if (parent[e.to] == -1 && e.cap > e.flow) {
parent[e.to] = nod;
parentIndex[e.to] = i;
q.push(e.to);
}
}
}
if (parent[d] == -1) {
return 0; // nu mai exista drum de augmentare
}
// determinam fluxul minim pe drumul gasit
int flow = INF;
int curr = d;
while (curr != s) {
int prev = parent[curr];
int edgeIndex = parentIndex[curr];
// actualizam fluxul minim
flow = min(flow, grafic[prev][edgeIndex].cap - grafic[prev][edgeIndex].flow);
curr = prev;
}
curr = d;
while (curr != s) {
int prev = parent[curr];
int edgeIndex = parentIndex[curr];
// adaugam flux pe muchia directa
grafic[prev][edgeIndex].flow += flow;
// scadem flux pe muchia inversa
int revIndex = grafic[prev][edgeIndex].rev;
grafic[curr][revIndex].flow -= flow;
curr = prev;
}
return flow;
}
void add_adge(int from, int to, int cap) {
edge forward = {to, (int)grafic[to].size(), cap, 0};
edge backward = {from, (int)grafic[from].size(), 0, 0};
grafic[from].push_back(forward);
grafic[to].push_back(backward);
}
int main() {
ifstream fin("cuplaj.in");
ofstream fout("cuplaj.out");
int n, m, e;
fin >> n >> m >> e;
int sursa = 0;
int destinatie = n + m + 1;
// de la sursa catre partea stanga
for (int i = 1; i <= n; ++i) {
add_adge(sursa, i, 1);
}
// de la dreapta la destinatie
for (int i = 1; i <= m; ++i) {
add_adge(i + n, destinatie, 1);
}
// muchiile din graf
for (int i = 0; i < e; ++i) {
int u, v;
fin >> u >> v;
add_adge(u, v + n, 1);
}
int maxFlow = 0;
while (true) {
int flow = bfs(sursa, destinatie);
if (flow == 0) {
break; // nu mai exista drumuri de augmentare
}
maxFlow += flow;
}
fout << maxFlow << "\n";
// afisarea cuplajului
for (int u = 1; u <= n; ++u) {
for (auto &e : grafic[u]) {
// daca exista flux pe muchie, atunci face parte din cuplaj
if (e.to != sursa && e.flow > 0) {
fout << u << " " << e.to - n << "\n";
}
}
}
fin.close();
fout.close();
return 0;
}