Pagini recente » Cod sursa (job #2581574) | Cod sursa (job #115436) | Cod sursa (job #358740) | Cod sursa (job #660540) | Cod sursa (job #1396054)
// O(V * E)
#include <fstream>
#include <vector>
#include <cstring>
#define MAXV 10001
using namespace std;
ifstream in("cuplaj.in");
ofstream out("cuplaj.out");
int L, R, E;
vector <int> G[MAXV];
int matchOfL[MAXV]; // i in L, matchOfL[i] in R
int matchOfR[MAXV]; // i in R, matchOfR[i] in L
bool used[MAXV];
int maxMatch = 0;
inline void readAndBuild() {
in >> L >> R >> E;
int x, y;
for (int e = 0; e < E; ++ e) {
in >> x >> y;
G[x].push_back(y);
// I do not need to push the reverse edge into the graph
// because when finding an alternating (augmenting) path
// the nodes that are on R side, always follow an edge that is in M
// and because there is only on edge in M with some vertex v on it
// we know that there is only one way to go back on L side
}
}
inline bool dfs(int node) {
// the dfs will present nodes only from L side
// a node may be expanded at most once
if (used[node]) {
return false;
}
used[node] = true;
// *it is always from R side
for (vector <int>::iterator it = G[node].begin(); it != G[node].end(); ++ it) {
// if *it is not matched, then it can be matched with node
// push edge (node, *it) into M
if (matchOfR[*it] == 0) {
matchOfL[node] = *it;
matchOfR[*it] = node;
return true;
// if *it is matched then try to follow the path
// until we eventually end up with an unmatched node
} else {
bool isPath = dfs(matchOfR[*it]);
// if the path ended with an unmatched node then
// augment the path
// (augmentation is done as the dfs goes back)
if (isPath) {
matchOfL[node] = *it;
matchOfR[*it] = node;
return true;
}
}
}
return false;
}
inline void bipartiteMatchingEdmondsBlossomSimplified() {
bool foundPath = true;
while (foundPath) {
foundPath = false;
memset(used, false, sizeof(used));
for (int root = 1; root <= L; ++ root) {
if (matchOfL[root] == 0) {
foundPath = dfs(root);
if (foundPath) {
maxMatch ++;
// every time a path is found,
// reset the dfs
break;
}
}
}
}
}
inline void printResult() {
out << maxMatch << '\n';
for (int i = 1; i <= L; ++ i) {
if (matchOfL[i]) {
out << i << ' ' << matchOfL[i] << '\n';
}
}
}
int main() {
readAndBuild();
bipartiteMatchingEdmondsBlossomSimplified();
printResult();
return 0;
}