Files
troupe-standup/wizard-work/beam/hopcroft_karp.py
T

60 lines
1.6 KiB
Python

"""Hopcroft-Karp maximum bipartite matching (O(E sqrt(V))).
Graph is given as adjacency from left vertices 0..nL-1 to right vertices
0..nR-1. Returns (size, matchL, matchR) where matchL[u] = v or -1 and
matchR[v] = u or -1.
"""
from collections import deque
def hopcroft_karp(adj, n_left, n_right):
INF = 10 ** 9
pair_u = [-1] * n_left
pair_v = [-1] * n_right
dist = [0] * n_left
def bfs():
q = deque()
for u in range(n_left):
if pair_u[u] == -1:
dist[u] = 0
q.append(u)
else:
dist[u] = INF
found = False
while q:
u = q.popleft()
if dist[u] < INF:
for v in adj[u]:
pu = pair_v[v]
if pu != -1 and dist[pu] == INF:
dist[pu] = dist[u] + 1
q.append(pu)
elif pu == -1:
found = True
return found
def dfs(u):
if u != -1:
for v in adj[u]:
pu = pair_v[v]
if pu == -1 or (dist[pu] == dist[u] + 1 and dfs(pu)):
pair_u[u] = v
pair_v[v] = u
return True
dist[u] = INF
return False
return True
matching = 0
while bfs():
for u in range(n_left):
if pair_u[u] == -1:
if dfs(u):
matching += 1
return matching, pair_u, pair_v
def max_bipartite_matching(adj, n_left, n_right):
return hopcroft_karp(adj, n_left, n_right)