1 bipartite graph (bipartite graph)
- A bipartite graph is a special kind of graph that can be divided into two parts, and the points in each part are not connected to each other.
- The Hungarian algorithm is mainly used to solve two problems: finding the maximum number of matches and the minimum number of points covered in a bipartite graph .
2 Maximum matching problem
2.1 Problem description
- There are two point sets left and right, how many edges can we find at most without a common endpoint?
2.2 Example of Hungarian Algorithm
- Starting from B1, traverse from G1~G4 one by one
- First traverse to G2 that has an edge with B1
- Temporarily connect B1 and G2
- Then look at B2, and also traverse from G1~G4 one by one
- First traverse to G2 that has an edge with B2
- At this point G2 has been connected to B1 on the left
- So go back and look at B1 to see if there are other options for connecting to B1
- It is found that B1 can still connect to G4 after G2
- ——> B2 temporarily connected to G2, B1 temporarily connected to G4
- Then look at B3, first B3 will first traverse to G1
- G no conflict
- Last look at B4
- B4 traverses to G4
- G4 is now connected to B1
- B1 has nothing else to connect to
- ——>B4 cannot connect to G4
2.3 Python implementation
2.3.1 Data and preparation section
# 左点-右点--邻接矩阵
ada_matrix=[[0,1,0,1],
[0,1,0,0],
[1,0,1,0],
[0,0,0,1]]
num_left=len(ada_matrix)
num_right=len(ada_matrix[0])
right_pair=[-1]*num_right
#右点和哪个左点匹配了(一开始都是-1,表示没有匹配)
2.3.2 if_match function
- Indicates that when the left point matches i, according to the situation of right_visited, whether the left point i will match a right point
- right_visited indicates whether each right point has been considered in the process of matching the left point i
def if_match(i):
global right_visited
for j in range(num_right):
if(ada_matrix[i][j]==1 and right_visited[j]==0):
#如果右边的点和左边的点有连边;同时在考虑左点i的过程中,右点j没有被考虑过
right_visited[j]=1
if(right_pair[j]==-1):
#如果左边的点现在还没有右边的点和他匹配,那么左点i和右点j连接
right_pair[j]=i
return True
#左点遍历到i的时候,暂时可以匹配j(后续i点可能需要“改嫁”,但是如果只遍历到i,是不冲突的)
elif(if_match(right_pair[j])):
right_pair[j]=i
#如果左边的点已经和别的点(right_pair[j])匹配了,那么看看(right_pair[j])能不能“改嫁”
#也就是看看不能选择j的情况下,(right_pair[j])能不能匹配到其他的右点
#这是一个递归过程,进行if_match(right_pair[j])的时候,假设匹配到新的右点j'
#又需要判断j'是否有点和它匹配+如果匹配了,已经匹配的点能不能“改嫁”
return True
#左点遍历到i的时候,暂时可以匹配j(后续i点可能需要“改嫁”,但是如果只遍历到i,是不冲突的)
return False
2.3.3 Main function
for i in range(num_left):
#每一个左边的点
global right_visited
right_visited=[0]*num_right
#在考虑左边的点i的时候,右边的点有没有被考虑过
print(right_pair)
if_match(i)
'''
[-1, -1, -1, -1]
[-1, 0, -1, -1]
[-1, 1, -1, 0]
[2, 1, -1, 0]
'''
The result is the same as the previous manual derivation
3 Minimum point covering problem
- Find the fewest points such that all edges of the bipartite graph have at least one endpoint among these points.
- In other words, if you delete the edges containing these points, you can delete all the edges
- König's theorem: The maximum number of matchings in a bipartite graph is equal to the minimum number of point covers in this graph
Reference content: Get you started with multi-target tracking (3) Hungarian algorithm & KM algorithm- Zhihu (zhihu.com)