On this page
article
Hopcroft Karp
Sobre
Computa matching maximo em grafo bipartido
’n’ e ’m’ sao quantos vertices tem em cada particao
chamar add(i, j) para add aresta entre o cara i
da particao A, e o cara j da particao B
(entao i < n, j < m)
O(|E| * sqrt(|V|)) com constante baixa
Para grafos esparsos gerados aleatoriamente, roda em O(|E| * log(|V|))
com alta probabilidade
Link original: hopcroftKarp.cpp
Código
mt19937 rng((int) chrono::steady_clock::now().time_since_epoch().count());
struct hopcroft_karp {
int n, m;
vector<vector<int>> g;
vector<int> dist, nxt, ma, mb;
hopcroft_karp(int n_, int m_) : n(n_), m(m_), g(n),
dist(n), nxt(n), ma(n, -1), mb(m, -1) {}
void add(int a, int b) { g[a].push_back(b); }
bool dfs(int i) {
for (int &id = nxt[i]; id < g[i].size(); id++) {
int j = g[i][id];
if (mb[j] == -1 or (dist[mb[j]] == dist[i] + 1 and dfs(mb[j]))) {
ma[i] = j, mb[j] = i;
return true;
}
}
return false;
}
bool bfs() {
for (int i = 0; i < n; i++) dist[i] = n;
queue<int> q;
for (int i = 0; i < n; i++) if (ma[i] == -1) {
dist[i] = 0;
q.push(i);
}
bool rep = 0;
while (q.size()) {
int i = q.front(); q.pop();
for (int j : g[i]) {
if (mb[j] == -1) rep = 1;
else if (dist[mb[j]] > dist[i] + 1) {
dist[mb[j]] = dist[i] + 1;
q.push(mb[j]);
}
}
}
return rep;
}
int matching() {
int ret = 0;
for (auto& i : g) shuffle(i.begin(), i.end(), rng);
while (bfs()) {
for (int i = 0; i < n; i++) nxt[i] = 0;
for (int i = 0; i < n; i++)
if (ma[i] == -1 and dfs(i)) ret++;
}
return ret;
}
};