soj1303 KM算法

来源:互联网 发布:淘宝能赚到钱吗 编辑:程序博客网 时间:2024/06/06 18:59

这是一道典型应用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 matchingGlobal 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 falseKM()    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
原创粉丝点击