Pagini recente » Cod sursa (job #2707149) | Cod sursa (job #960822) | Cod sursa (job #3183931) | Cod sursa (job #549297) | Cod sursa (job #3272254)
#include <bits/stdc++.h>
using namespace std;
ifstream fin("cuplaj.in");
ofstream fout("cuplaj.out");
struct Muchii {
int x, y;
};
Muchii muchii[10003];
int N, n, m, k, x, y, g[10001][10001], maxflow;
queue<int> q;
bool viz[10001];
int parent[10001];
void read()
{
fin >> n >> m >> k;
/// S=0, multimea A = {1,2...,n}, multimea B = {n+1,...,n+m}, T=n+m+1
N = n + m + 1;
for (int i = 0; i < k; ++i)
{
fin >> x >> y;
g[x][y + n] = 1;
muchii[i].x = x;
muchii[i].y = y + n;
}
/// adaugam muchii de la sursa la fiecare nod din multimea A
for (int i = 1; i <= n; ++i)
g[0][i] = 1;
/// adaugam muchii de la fiecare nod din multimea B la sink
for (int i = n + 1; i <= n + m; ++i)
g[i][n + m + 1] = 1;
}
void afis() {
for (int i = 0; i <= N; ++i) {
for (int j = 0; j <= N; ++j)
cout << g[i][j] << " ";
cout << "\n";
}
}
int bfs()
{
/// folosim bfs pentru a verifica daca mai este un drum de la s la t
/// folosim vectorul parent pentru a putea reconstrui drumul
/// reinitializam tot
while (!q.empty())
q.pop();
for (int i = 0; i <= N; i++)
{
parent[i] = 0;
viz[i] = false;
}
q.push(0);
viz[0] = 1;
/// bfs
while (!q.empty())
{
auto nod = q.front();
q.pop();
/// n reprezinta destinatia deci returnam true deoarece am gasit drum
if (nod == N) return true;
for (int i = 0; i <= N; i++)
if (!viz[i] && g[nod][i] > 0)
{
q.push(i);
parent[i] = nod;
viz[i] = true;
}
}
return false;
}
inline int flux()
{
/// cat timp avem drumuri
while (bfs())
{
for (int i = 0; i <= N; i++)
{
if (g[i][N] > 0 && viz[i])
{
int leaf = i;
/// construim drumul
vector <int> path;
path.push_back(N);
path.push_back(leaf);
int nod = parent[leaf];
if (nod == 0)
path.push_back(nod);
else
{
while (nod != 0)
{
path.push_back(nod);
nod = parent[nod];
}
path.push_back(0);
}
reverse(path.begin(), path.end());
/// dupa ce am gasit drumul, vedem care este flow-ul minim si adaugam la rezultatul final
int flow_minim = INT_MAX;
for (int j = 0; j < path.size() - 1; j++)
flow_minim = min(flow_minim, g[path[j]][path[j + 1]]);
maxflow += flow_minim;
/// pt reconstruirea flow-ului
/// scadem flow_minim din muchiile inspre destinatie si adunam pe muchiile in directie opusa
for (int j = 0; j < path.size() - 1; j++)
{
g[path[j]][path[j + 1]] -= flow_minim;
g[path[j + 1]][path[j]] += flow_minim;
}
}
}
}
return maxflow;
}
int main()
{
read();
fout << flux() << "\n";
for (int i = 0; i < k; ++i) {
x = muchii[i].x;
y = muchii[i].y;
if (g[x][y] == 0)
fout << x << " " << y - n << '\n';
}
return 0;
}