Pagini recente » Cod sursa (job #222775) | Cod sursa (job #532391) | Cod sursa (job #698214) | Cod sursa (job #876979) | Cod sursa (job #1396053)
#include <fstream>
#include <list>
#include <queue>
#define MAXV 10003
using namespace std;
ifstream in("cuplaj.in");
ofstream out("cuplaj.out");
class edge {
public:
int fromNode, toNode, c, f1;
edge* revEdge;
edge(int fromNode, int toNode, int c, int f1) {
this -> fromNode = fromNode;
this -> toNode = toNode;
this -> c = c;
this -> f1 = f1;
}
};
int L, R, E;
list <edge*> Gf[2 * MAXV];
int s, t;
list <edge*>::iterator path[2 * MAXV];
int maxFlow = 0;
int match[MAXV];
inline void readAndBuild() {
in >> L >> R >> E;
s = L + R + 1;
t = L + R + 2;
int x, y;
for (int e = 0; e < E; ++ e) {
in >> x >> y;
Gf[x].push_back(new edge(x, y + L, 1, 0));
Gf[y + L].push_back(new edge(y + L, x, 0, 0));
Gf[x].back() -> revEdge = *Gf[y + L].rbegin();
Gf[y + L].back() -> revEdge = *Gf[x].rbegin();
}
for (int node = 1; node <= L; ++ node) {
Gf[s].push_back(new edge(s, node, 1, 0));
Gf[node].push_back(new edge(node, s, 0 , 0));
Gf[s].back() -> revEdge = *Gf[node].rbegin();
Gf[node].back() -> revEdge = *Gf[s].rbegin();
}
for (int node = 1 + L; node <= R + L; ++ node) {
Gf[node].push_back(new edge(node, t, 1 , 0));
Gf[t].push_back(new edge(t, node, 0, 0));
Gf[node].back() -> revEdge = *Gf[t].rbegin();
Gf[t].back() -> revEdge = *Gf[node].rbegin();
}
}
inline bool bfs() {
bool sinkReached = false;
queue <int> q;
q.push(s);
for (int i = L + R; i > 0; -- i) {
path[i] = Gf[0].end();
}
path[s] = Gf[0].begin(); // not 0, but something else (I never need this)
path[t] = Gf[0].end(); // initialised to 0
for (int node = q.front(); !q.empty(); node = q.front()) {
q.pop();
for (list <edge*>::iterator it = Gf[node].begin(); it != Gf[node].end(); ++ it) {
if (path[(*it) -> toNode] == Gf[0].end() && (*it) -> f1 < (*it) -> c) {
if ((*it) -> toNode == t) {
sinkReached = true;
} else {
path[(*it) -> toNode] = it;
q.push((*it) -> toNode);
}
}
}
}
return sinkReached;
}
inline void bipartiteMatchingWithDinicVariation() {
for (bool sinkReached = bfs(); sinkReached; sinkReached = bfs()) {
for (list <edge*>::iterator it = Gf[t].begin(); it != Gf[t].end(); ++ it) {
if (path[(*it) -> toNode] != Gf[0].end() && (*it) -> revEdge -> f1 < (*it) -> revEdge -> c) {
int cfpath = (*it) -> revEdge -> c - (*it) -> revEdge -> f1;
for (int node = (*it) -> toNode; node != s; node = (*path[node]) -> fromNode) {
if (cfpath > (*path[node]) -> c - (*path[node]) -> f1) {
cfpath = (*path[node]) -> c - (*path[node]) -> f1;
}
}
if (cfpath == 0) continue;
maxFlow += cfpath;
// we have to manually change the flow for the edge and the reverse edge
// between the possible father (x = (*it) -> toNode) and t
// because we do not have an iterator for this edge (x, t)
// (we have the iterator for the reverse edge (t, x))
(*it) -> f1 -= cfpath;
(*it) -> revEdge -> f1 += cfpath;
for (int node = (*it) -> toNode; node != s; node = (*path[node]) -> fromNode) {
int fromNode = (*path[node]) -> fromNode;
int toNode = (*path[node]) -> toNode;
if (fromNode != s && fromNode != t && toNode != s && toNode != t) {
if (fromNode < toNode) {
match[fromNode] = toNode;
}
}
(*path[node]) -> f1 += cfpath;
(*path[node]) -> revEdge -> f1 -= cfpath;
}
}
}
}
}
inline void printResult() {
out << maxFlow << '\n';
for (int i = 1; i <= L; ++ i) {
if (match[i]) {
out << i << ' ' << match[i] - L << '\n';
}
}
}
int main() {
readAndBuild();
bipartiteMatchingWithDinicVariation();
printResult();
return 0;
}