文章目录
https://article.itxueyuan.com/Aeava9
程序运行结果:
--x=0--
1 - 1
--x=1--
1 - 1
2 - 2
--x=2--
3 - 1
1 - 2
2 - 3
--x=3--
3 - 1
1 - 2
2 - 3
import numpy as np
def node_map_to_adj_matrix(node_map):
L = max(node_map.keys())
adj=np.zeros([L,L],dtype=np.int32)
for u in node_map:
for v in node_map[u]:
adj[u-1,v-1]=1
return adj
def dfs(x:int, N:int, adj, vis, match)->bool:
'''女生 X 男生 Y
:param N:
:param x:
:param adj:
:param vis: Y是否被使用
:param match: 记录Yi选择的X编号,未被选则0
:return:
'''
# 遍历所有Y
x=int(x)
for y in range(N):
# 如果xy联通并且y没有被使用
if adj[x,y]==1 and vis[y]==0:
vis[y]=1
# 如果choice[y]没有被占用或者能把占用boy[i]的人换一个连线,短路原则: 如果没有被占用则不会执行后面的部分
if match[y]==-1 or dfs(match[y], N, adj, vis, match):
match[y]=x
return True
return False
def print_edge_by_choice(choice):
for i,e in enumerate(choice):
if e!=-1:
e=int(e)
print(e+1,'-',i+1)
def Hungarian_main(adj, N):
choice = -1 * np.ones([N])
for x in range(4):
print(f'--x={x:d}--')
vis=np.zeros([N])
ret=dfs(x,N,adj,vis,choice)
# print(choice)
print_edge_by_choice(choice)
if __name__ == '__main__':
node_map = {
1: [1, 2],
2: [2, 3],
3: [1, 2],
4: [3]
}
adj=node_map_to_adj_matrix(node_map)
N=4
Hungarian_main(adj, N)
KM 算法
https://blog.csdn.net/chenshibo17/article/details/79933191
import numpy as np
def node_map_to_adj_matrix(node_map):
L = max(node_map.keys())
adj = np.zeros([L, L], dtype=np.int32)
for u in node_map:
for v, w in node_map[u]:
adj[u - 1, v - 1] = w
return adj
def dfs(x: int, N: int, ex_x, ex_y, vis_x, vis_y, match, slack) -> bool:
x=int(x)
vis_x[x] = True
for y in range(N):
if vis_y[y]:
continue
gap = ex_x[x] + ex_y[y] - adj[x][y]
if gap == 0:
vis_y[y] = True
if match[y] == -1 or dfs(match[y], N, ex_x, ex_y, vis_x, vis_y, match, slack):
match[y] = x
return True
else:
slack[y] = min(slack[y], gap)
return False
def KM_main(adj: np.ndarray, N):
ex_x = adj.max(axis=1)
ex_y = np.zeros([N], dtype='int')
match = np.ones([N], dtype='int') * -1
for x in range(N):
slack = np.ones([N], dtype='int') * np.inf
while True:
vis_x = np.zeros([N], dtype='bool')
vis_y = np.zeros([N], dtype='bool')
# 如果匹配成功,退出
if dfs(x, N, ex_x, ex_y, vis_x, vis_y, match, slack):
break
d = np.inf
for j in range(N):
if not vis_y[j]:
d=min(d,slack[j])
print('d',d)
for j in range(N):
if vis_x[j] :
ex_x[j]-=d
if vis_y[j]:
ex_y[j]+=d
else:
slack[j]-=d
print(match)
if __name__ == '__main__':
node_map = {
1: [(1, 3), (3, 4)],
2: [(1, 2), (2, 1), (3, 3)],
3: [(3, 5)]
}
N = 3
adj = node_map_to_adj_matrix(node_map)
KM_main(adj, N)