60 lines
1.6 KiB
Python
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)
|