#include <iostream>
#include <queue>
#include <vector>
using namespace std;
vector< pair<int,int> >
find_maximum_matching(
int A,
int B,
const vector< pair<int,int> > &edge_list)
{
vector< vector<int> > BA;
BA.resize(B);
for (const auto &e : edge_list) BA[ e.second ].push_back( e.first );
vector<int> match(A,-1);
for (int b=0; b<B; ++b) {
vector<int> from(A,-1);
queue<int> Q;
for (int a : BA[b]) { Q.push(a); from[a]=a; }
while (!Q.empty()) {
int a = Q.front(); Q.pop();
if (match[a] == -1) {
while (from[a] != a) { match[a] = match[from[a]]; a = from[a]; }
match[a] = b;
break;
} else {
for (int x : BA[match[a]]) if (from[x]==-1) { Q.push(x); from[x]=a; }
}
}
}
vector< pair<int,int> > result;
for (int a=0; a<A; ++a) if (match[a] != -1) result.push_back( { a, match[a] } );
return result;
}
int main() {
vector< pair<int,int> > edge_list = { {0,0}, {0,1}, {0,2}, {1,0}, {2,0} };
cout << find_maximum_matching(3, 3, edge_list).size() << endl;
}
I2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8cXVldWU+CiNpbmNsdWRlIDx2ZWN0b3I+CnVzaW5nIG5hbWVzcGFjZSBzdGQ7Cgp2ZWN0b3I8IHBhaXI8aW50LGludD4gPgpmaW5kX21heGltdW1fbWF0Y2hpbmcoCiAgICAgICAgaW50IEEsCiAgICAgICAgaW50IEIsCiAgICAgICAgY29uc3QgdmVjdG9yPCBwYWlyPGludCxpbnQ+ID4gJmVkZ2VfbGlzdCkKewogICAgdmVjdG9yPCB2ZWN0b3I8aW50PiA+IEJBOwogICAgQkEucmVzaXplKEIpOwogICAgZm9yIChjb25zdCBhdXRvICZlIDogZWRnZV9saXN0KSBCQVsgZS5zZWNvbmQgXS5wdXNoX2JhY2soIGUuZmlyc3QgKTsKICAgIHZlY3RvcjxpbnQ+IG1hdGNoKEEsLTEpOwogICAgZm9yIChpbnQgYj0wOyBiPEI7ICsrYikgewogICAgICAgIHZlY3RvcjxpbnQ+IGZyb20oQSwtMSk7CiAgICAgICAgcXVldWU8aW50PiBROwogICAgICAgIGZvciAoaW50IGEgOiBCQVtiXSkgeyBRLnB1c2goYSk7IGZyb21bYV09YTsgfQogICAgICAgIHdoaWxlICghUS5lbXB0eSgpKSB7CiAgICAgICAgICAgIGludCBhID0gUS5mcm9udCgpOyBRLnBvcCgpOwogICAgICAgICAgICBpZiAobWF0Y2hbYV0gPT0gLTEpIHsKICAgICAgICAgICAgICAgIHdoaWxlIChmcm9tW2FdICE9IGEpIHsgbWF0Y2hbYV0gPSBtYXRjaFtmcm9tW2FdXTsgYSA9IGZyb21bYV07IH0KICAgICAgICAgICAgICAgIG1hdGNoW2FdID0gYjsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgZm9yIChpbnQgeCA6IEJBW21hdGNoW2FdXSkgaWYgKGZyb21beF09PS0xKSB7IFEucHVzaCh4KTsgZnJvbVt4XT1hOyB9CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICB9CiAgICB2ZWN0b3I8IHBhaXI8aW50LGludD4gPiByZXN1bHQ7CiAgICBmb3IgKGludCBhPTA7IGE8QTsgKythKSBpZiAobWF0Y2hbYV0gIT0gLTEpIHJlc3VsdC5wdXNoX2JhY2soIHsgYSwgbWF0Y2hbYV0gfSApOwogICAgcmV0dXJuIHJlc3VsdDsKfQoKaW50IG1haW4oKSB7CiAgICB2ZWN0b3I8IHBhaXI8aW50LGludD4gPiBlZGdlX2xpc3QgPSB7IHswLDB9LCB7MCwxfSwgezAsMn0sIHsxLDB9LCB7MiwwfSB9OwogICAgY291dCA8PCBmaW5kX21heGltdW1fbWF0Y2hpbmcoMywgMywgZWRnZV9saXN0KS5zaXplKCkgPDwgZW5kbDsKfQ==