这是一道典型应用KM算法的二分带权图最大匹配问题,第一次学习KM算法,有许多不懂得地方,参考了博客http://www.cnblogs.com/wenruo/p/5264235.html的详解,稍微懂了一点,把源代码翻译成了伪代码,如下
Algorithm KM(map[][], n)
Input: map[][], a two dimension array that records the power of the edge in a bipartite graph.
n, an integer, the size of the array
Output: The sum of the power of the greatest bipartite graph matching
Global variable
int ex_x[maxn] // x的期望值
int ex_y[maxn] // y的期望值
bool vis_x[maxn] // 每一轮匹配过的x集合
bool vis_y[maxn] // 每一轮匹配过的y集合
int match[maxn] // 当前y匹配到的x
int slack[maxn] // y被匹配最少再需期望
DFS(int x)
vis_x[x] = true
for y = 0 to N-1
if vis_y[y] then continue
gap = ex_x[x] + ex_y[y] – map[x][y]
if gap == 0 then
vis_y[y] = true
// 找到一个适合的y后,y还没被匹配,或y的原配能再找到匹配
if match[y] == -1 || DFS(match[y]) then
match[y] = x
return true
else slack[y] = min(slack[y], gap) // 不适合,y更新slack
return false
KM()
set(match, -1) // x=match[y],初始化为-1,为匹配状态
set(ex_y, 0) // y的期望初始化为0
// 对每个x0找到对应最大的map[x0][y],此步为贪心
for i = 0 to N-1
ex_x[i] = map[i][0]
for j = 0 to N-1
ex_x[i] = max(ex_x[i], map[i][j])
// 遍历每个x,去匹配一个y
for i = 0 to N-1
set(slack, INF) // 最少再需期望用到min,初始化为INF
while true
set(vis_x, false) // 重置已访问集合,下同
set(vis_y, false)
// 找到匹配,退出while
if DFS(i) then break
// 没有找到匹配,降低x期望,升高y期望
d = INF // d为最小可降低期望
for j = 0 to N-1
if !vis_y[j] then d = min(d, slack[j])
for j = 0 to N-1
if vis_x[j] then ex_x[j] -= d
if vis_y[j] then ex_y[j] += d
else slack[j] -= d
res = 0
for i = 0 to N-1
res += map[ match[i] ][i]
return res