Skip to content

Commit e3442dd

Browse files
authored
Update maximum-students-taking-exam.py
1 parent 2233cd3 commit e3442dd

File tree

1 file changed

+46
-8
lines changed

1 file changed

+46
-8
lines changed

Python/maximum-students-taking-exam.py

Lines changed: 46 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,19 +7,21 @@
77
import collections
88

99

10+
from functools import partial
11+
1012
# Time: O(E * sqrt(V))
1113
# Space: O(V)
1214
# Source code from http://code.activestate.com/recipes/123641-hopcroft-karp-bipartite-matching/
1315
# Hopcroft-Karp bipartite max-cardinality matching and max independent set
1416
# David Eppstein, UC Irvine, 27 Apr 2002
1517
def bipartiteMatch(graph):
1618
'''Find maximum cardinality matching of a bipartite graph (U,V,E).
17-
The input format is a dictionary mapping members of U to a list
18-
of their neighbors in V. The output is a triple (M,A,B) where M is a
19-
dictionary mapping members of V to their matches in U, A is the part
20-
of the maximum independent set in U, and B is the part of the MIS in V.
21-
The same object may occur in both U and V, and is treated as two
22-
distinct vertices if this happens.'''
19+
The input format is a dictionary mapping members of U to a list
20+
of their neighbors in V. The output is a triple (M,A,B) where M is a
21+
dictionary mapping members of V to their matches in U, A is the part
22+
of the maximum independent set in U, and B is the part of the MIS in V.
23+
The same object may occur in both U and V, and is treated as two
24+
distinct vertices if this happens.'''
2325

2426
# initialize greedy matching (redundant, but faster than full search)
2527
matching = {}
@@ -66,7 +68,7 @@ def bipartiteMatch(graph):
6668
if v not in preds:
6769
unlayered[v] = None
6870
return (matching,list(pred),list(unlayered))
69-
71+
7072
# recursively search backward through layers to find alternating paths
7173
# recursion returns true if found path, false otherwise
7274
def recurse(v):
@@ -82,7 +84,43 @@ def recurse(v):
8284
return 1
8385
return 0
8486

85-
for v in unmatched: recurse(v)
87+
def recurse_iter(v):
88+
def divide(v):
89+
if v not in preds:
90+
return
91+
L = preds[v]
92+
del preds[v]
93+
for u in L :
94+
if u in pred and pred[u] is unmatched: # early return
95+
del pred[u]
96+
matching[v] = u
97+
ret[0] = True
98+
return
99+
stk.append(partial(conquer, v, iter(L)))
100+
101+
def conquer(v, it):
102+
for u in it:
103+
if u not in pred:
104+
continue
105+
pu = pred[u]
106+
del pred[u]
107+
stk.append(partial(postprocess, v, u, it))
108+
stk.append(partial(divide, pu))
109+
return
110+
111+
def postprocess(v, u, it):
112+
if not ret[0]:
113+
stk.append(partial(conquer, v, it))
114+
return
115+
matching[v] = u
116+
117+
ret, stk = [False], []
118+
stk.append(partial(divide, v))
119+
while stk:
120+
stk.pop()()
121+
return ret[0]
122+
123+
for v in unmatched: recurse_iter(v)
86124

87125

88126
# Hopcroft-Karp bipartite matching

0 commit comments

Comments
 (0)