zoukankan      html  css  js  c++  java
  • 二分图最大匹配:匈牙利算法的python实现

    二分图匹配是很常见的算法问题,一般用匈牙利算法解决二分图最大匹配问题,但是目前网上绝大多数都是C/C++实现版本,没有python版本,于是就用python实现了一下深度优先的匈牙利算法,本文使用的是递归的方式以便于理解,然而迭代的方式会更好,各位可以自行实现。

    1、二分图、最大匹配

    什么是二分图:二分图又称作二部图,是图论中的一种特殊模型。 设G=(V,E)是一个无向图,如果顶点V可分割为两个互不相交的子集(A,B),并且图中的每条边(i,j)所关联的两个顶点i和j分别属于这两个不同的顶点集(i in A,j in B),则称图G为一个二分图。 

    什么是匹配:把上图想象成3位工人和4种工作,连线代表工人愿意从事某项工作,但最终1个工人只能做一种工作,最终的配对结果连线就是一个匹配。匹配可以是空。 
    什么是最大匹配:在愿意从事的基础上,能够最多配成几对。 

    现在要用匈牙利算法找出最多能发展几对。 
    [color=green][size=medium] 
    匈牙利算法是解决寻找二分图最大匹配的。

    更多二分图最大匹配的图解可以参考 http://xuxueliang.blog.51cto.com/5576502/1297344

    以下是代码,为了图省事使用了类,实际上并不需要这样

    M=[]
    class DFS_hungary():
    
        def __init__(self, nx, ny, edge, cx, cy, visited):
            self.nx, self.ny=nx, ny
            self.edge = edge
            self.cx, self.cy=cx,cy
            self.visited=visited
    
        def max_match(self):
            res=0
            for i in self.nx:
                if self.cx[i]==-1:
                    for key in self.ny:         # 将visited置0表示未访问过
                        self.visited[key]=0
                    res+=self.path(i)return res
    
        def path(self, u):
            for v in self.ny:
                if self.edge[u][v] and (not self.visited[v]):
                    self.visited[v]=1
                    if self.cy[v]==-1:
                        self.cx[u] = v
                        self.cy[v] = u
                        M.append((u,v))
                        return 1
                    else:
                        M.remove((self.cy[v], v))
                        if self.path(self.cy[v]):
                            self.cx[u] = v
                            self.cy[v] = u
                            M.append((u, v))
                            return 1
            return 0

    ok,接着测试一下:

    if __name__ == '__main__':
        nx, ny = ['A', 'B', 'C', 'D'], ['E', 'F', 'G', 'H']
        edge = {'A':{'E': 1, 'F': 0, 'G': 1, 'H':0}, 'B':{'E': 0, 'F': 1, 'G': 0, 'H':1}, 'C':{'E': 1, 'F': 0, 'G': 0, 'H':1}, 'D':{'E': 0, 'F': 0, 'G': 1, 'H':0}} # 1 表示可以匹配, 0 表示不能匹配
        cx, cy = {'A':-1,'B':-1,'C':-1,'D':-1}, {'E':-1,'F':-1,'G':-1,'H':-1}
        visited = {'E': 0, 'F': 0, 'G': 0,'H':0}
    
        print DFS_hungary(nx, ny, edge, cx, cy, visited).max_match()

    结果为4,是正确的。各位也可以使用其它二分图来测试。

    ---------------------------------------------------------补充BFS版本匈牙利算法-------------------------------------------------------

      BFS版本的匈牙利算法性能更好一些,但是比较难理解,下面把BFS版本的算法也贴出来,也是翻译自c++版本,这次使用更好的迭代方式替换了递归方式

    def BFS_hungary(g,Nx,Ny,Mx,My,chk,Q,prev):
        res=0
        for i in xrange(Nx):
            if Mx[i]==-1:
                qs=qe=0
                Q[qe]=i
                qe+=1
                prev[i]=-1
    
                flag=0
                while(qs<qe and not flag):
                    u=Q[qs]
                    for v in xrange(Ny):
                        if flag:continue
                        if g[u][v] and chk[v]!=i:
                            chk[v]=i
                            Q[qe]=My[v]
                            qe+=1
                            if My[v]>=0:
                                prev[My[v]]=u
                            else:
                                flag=1
                                d,e=u,v
                                while d!=-1:
                                    t=Mx[d]
                                    Mx[d]=e
                                    My[e]=d
                                    d=prev[d]
                                    e=t
                    qs+=1
                if Mx[i]!=-1:
                    res+=1
        return res

    测试一下:

    if __name__ == '__main__':
           g=[[1,0,1,0],[0,1,0,1],[1,0,0,1],[0,0,1,0]]
           Nx=4
           Ny=4
           Mx=[-1,-1,-1,-1]
           My=[-1,-1,-1,-1]
           chk=[-1,-1,-1,-1]
           Q=[0 for i in range(100)]
        prev=[0,0,0,0]
    print BFS_hungary()

    结果为4,正确

  • 相关阅读:
    Python 魔法方法
    使用PHP7来批量更新MangoDB数据
    git 小乌龟安装教程
    webpack初学者(1)
    移动端与PC端的触屏事件
    解决onclick事件的300ms延时问题
    尺寸单位em,rem,vh,vw
    ngRoute 与ui.router区别
    angular.js的依赖注入解析
    ionic的基础学习(第一篇)
  • 原文地址:https://www.cnblogs.com/jamespei/p/5555734.html
Copyright © 2011-2022 走看看