Pagini recente » Cod sursa (job #870289) | Cod sursa (job #1971115) | Cod sursa (job #1964887) | Cod sursa (job #1862463) | Cod sursa (job #1394931)
#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;
// must use list iterators, and not vector iterators
// because the iterators from vector change when the size of the vector is doubled
// and the whole container is reallocated to different addresses
// the same does not apply to lists, where the addresses of the iterators remain fixed
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 i = 1; i <= L; ++ i) {
Gf[s].push_back(*new edge(s, i, 1, 0));
Gf[i].push_back(*new edge(i, s, 0, 0));
Gf[s].back().revEdge = &*Gf[i].rbegin();
Gf[i].back().revEdge = &*Gf[s].rbegin();
}
for (int i = 1 + L; i <= R + L; ++ i) {
Gf[i].push_back(*new edge(i, t, 1, 0));
Gf[t].push_back(*new edge(t, i, 0, 0));
Gf[i].back().revEdge = &*Gf[t].rbegin();
Gf[t].back().revEdge = &*Gf[i].rbegin();
}
}
inline bool bfs() {
queue <int> q;
q.push(s);
for (int i = 1; i <= L + R; ++ i) {
path[i] = Gf[0].end(); // means "not set"
}
path[s] = Gf[0].end();
path[t] = Gf[0].end();
for (int node = q.front(); !q.empty(); node = q.front()) {
q.pop();
if (node == t) {
return true;
}
for (list <edge>::iterator it = Gf[node].begin(); it != Gf[node].end(); ++ it) {
if (path[(*it).toNode] == Gf[0].end() && (*it).f1 < (*it).c) {
path[(*it).toNode] = it;
q.push((*it).toNode);
}
}
}
return false;
}
inline void bipartiteMatchWithEdmondsKarp() {
for (bool isPath = bfs(); isPath; isPath = bfs()) {
int cfpath = (*path[t]).c - (*path[t]).f1;
for (int node = (*path[t]).fromNode; node != s; node = (*path[node]).fromNode) {
if (cfpath > (*path[node]).c - (*path[node]).f1) {
cfpath = (*path[node]).c - (*path[node]).f1;
}
}
maxFlow += cfpath;
for (int node = t; node != s; node = (*path[node]).fromNode) {
int fromNode = (*path[node]).fromNode;
int toNode = node;
if (fromNode != s && fromNode != t && toNode != s && toNode != t) {
if (fromNode < toNode) {
match[fromNode] = toNode;
} else {
match[fromNode] = 0;
}
}
(*path[node]).f1 += cfpath;
(*((*path[node]).revEdge)).f1 -= cfpath;
}
printf("\n");
}
}
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();
bipartiteMatchWithEdmondsKarp();
printResult();
return 0;
}