7
7
import collections
8
8
9
9
10
+ from functools import partial
11
+
10
12
# Time: O(E * sqrt(V))
11
13
# Space: O(V)
12
14
# Source code from http://code.activestate.com/recipes/123641-hopcroft-karp-bipartite-matching/
13
15
# Hopcroft-Karp bipartite max-cardinality matching and max independent set
14
16
# David Eppstein, UC Irvine, 27 Apr 2002
15
17
def bipartiteMatch (graph ):
16
18
'''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.'''
23
25
24
26
# initialize greedy matching (redundant, but faster than full search)
25
27
matching = {}
@@ -66,7 +68,7 @@ def bipartiteMatch(graph):
66
68
if v not in preds :
67
69
unlayered [v ] = None
68
70
return (matching ,list (pred ),list (unlayered ))
69
-
71
+
70
72
# recursively search backward through layers to find alternating paths
71
73
# recursion returns true if found path, false otherwise
72
74
def recurse (v ):
@@ -82,7 +84,43 @@ def recurse(v):
82
84
return 1
83
85
return 0
84
86
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 )
86
124
87
125
88
126
# Hopcroft-Karp bipartite matching
0 commit comments