-
Notifications
You must be signed in to change notification settings - Fork 0
/
hopcroft.py
87 lines (77 loc) · 2.24 KB
/
hopcroft.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
import numpy as np
from collections import deque
import math
from utils import genGraph, printGraph,printGraphWithMatching
def hopcroft(G,A):
M={}
visit={}
for i in range(len(G)):
M[str(i)]=-1
has_aug_path=True
it=0
while has_aug_path:
it+=1
print("iter :",it)
if it==3: break
for u in range(len(G)):
visit[str(u)]=0
has_aug_path=False
l=math.inf
L=bfs(G,A,M)
for u in L.keys():
if int(u)>=A and M[str(u)]==-1 and L[u]!=math.inf:
has_aug_path=True
l=min(l,L[u]) # shortest augmenting path to free vertex in B
for u in range(A):
if visit[str(u)]==0 and M[str(u)]==-1:
aug(u,G,A,L,M,l,visit)
return M
def bfs(G,A,M=None):
q = deque()
L={}
bfsvisit={}
for v in range(len(G)):
bfsvisit[str(v)]=0
L[str(v)]=math.inf
# visit is a dictionary, which key is vertice,
#value is 0 if unvisited, and 1 if visited
for v in range(A):
if M[str(v)]==-1:
q.append(v)
L[str(v)]=1
while len(q)>0:
v=q.popleft()
bfsvisit[str(v)]=1
if v < A:
for u in range(A,len(G)):
if G[v,u]==1:
if bfsvisit[str(u)]==0:
L[str(u)]= L[str(v)]+1
q.append(u)
else:
if M[str(v)]!=-1:
L[str(M[str(v)])]= L[str(v)]+1
q.append ( M[str(v)])
return L
def aug (u,G,A,L,M,l,visit):
visit[str(u)]=1
for v in range(A,len(G)):
if G[u,v]==1:
if M[str(v)]==-1:
visit[str(v)]=1
M[str(v)]=u
M[str(u)]=v
return True
elif visit[str(v)]==0 and L[str(v)]==L[str(u)]+1:
visit[str(v)]=1
if L[str(v)] <l and visit[str(M[str(v)])]==0 and aug(M[str(v)],G,A,L,M,l,visit):
M[str(v)]=u
M[str(u)]=v
return True
return False
if __name__=="__main__":
G2=genGraph(mode="random",size=16)
A=len(G2)//2
printGraph(G2,A)
M=hopcroft (G2,A)
printGraphWithMatching(G2,A,M)