Python 朱留爱德蒙';s算法(用于有向图)

Python 朱留爱德蒙';s算法(用于有向图),python,algorithm,graph,directed-graph,spanning-tree,Python,Algorithm,Graph,Directed Graph,Spanning Tree,我喜欢在有向图(有时可能有圈)中找到最小生成树(甚至森林)。解释的那个有一些错误。在Python中是否有任何用于此算法的包/代码能够实际工作?尽管我没有使用它,但它是GitHub的一个实现。 我把它的精髓附在下面。 由于它是一个GitHub存储库,所以可能会发生变化,因此最好从那里使用代码。 如果您使用此选项,请将作者归功于: 导入系统 def_输入(文件名): 价格={} 名称={} 对于文件中的行(文件名).readlines(): (名称、src、dst、price)=line.rstri

我喜欢在有向图(有时可能有圈)中找到最小生成树(甚至森林)。解释的那个有一些错误。在Python中是否有任何用于此算法的包/代码能够实际工作?

尽管我没有使用它,但它是GitHub的一个实现。 我把它的精髓附在下面。 由于它是一个GitHub存储库,所以可能会发生变化,因此最好从那里使用代码。 如果您使用此选项,请将作者归功于:

导入系统 def_输入(文件名): 价格={} 名称={} 对于文件中的行(文件名).readlines(): (名称、src、dst、price)=line.rstrip().split() name=int(name.replace('M','') src=int(src.replace('C','') dst=int(dst.replace('C','') 价格=整数(价格) t=(src,dst) 如果价格中的t和价格[t]w: MineExternal=(s,t) 最小修改重量=w u、 w=rg[minExternal[0]].popitem() rem=(MineExternal[0],u) rg[minExternal[0]].clear() 如果rg中的minExternal[1]: rg[MineExternal[1]][MineExternal[0]]=w 其他: rg[minExternal[1]]={minExternal[0]:w} 如果g中的rem[1]: 如果g[rem[1]]中的rem[0]: del g[rem[1]][rem[0]] 如果g中有minExternal[1]: g[MineExternal[1]][MineExternal[0]]=w 其他: g[minExternal[1]]={minExternal[0]:w} def mst(根,G): RG=_反向(G) 如果根在RG中: RG[root]={} g={} 对于RG中的n: 如果len(RG[n])==0: 持续 最小值=sys.maxint s、 d=无,无 对于RG[n]中的e: 如果RG[n][e]<最小值: 最小值=RG[n][e] s、 d=n,e 如果d在g中: g[d][s]=RG[s][d] 其他: g[d]={s:RG[s][d]} 周期=[] 访问=设置() 对于n in g: 如果n未访问: 周期=_getCycle(n,g,已访问) cycles.append(循环) rg=_反向(g) 对于循环中的循环: 如果根在循环中: 持续 _合并周期(周期,G,RG,G,RG) 返回g 如果名称=“\uuuuu main\uuuuuuuu”: 尝试: filename=sys.argv[1] root=sys.argv[2] 除索引器外: sys.stderr.write('未指定输入和/或根节点\n') sys.stderr.write('用法:python-edmonds.py\n') 系统出口(1) 价格,名称=_输入(文件名) g=_负载(价格、价格) h=mst(整数(根),g) 对于h中的s: 对于h[s]中的t: 打印“%d-%d”%(s,t)
我们非常感谢您的帮助。
    import sys


def _input(filename):
    prices = {}
    names = {}

    for line in file(filename).readlines():
        (name, src, dst, price) = line.rstrip().split()
        name = int(name.replace('M',''))
        src = int(src.replace('C',''))
        dst = int(dst.replace('C',''))
        price = int(price)
        t = (src,dst)
        if t in prices and prices[t] <= price:
            continue
        prices[t] = price
        names[t] = name

    return prices,names

def _load(arcs,weights):
    g = {}
    for (src,dst) in arcs:
        if src in g:
            g[src][dst] = weights[(src,dst)]
        else:
            g[src] = { dst : weights[(src,dst)] }
    return g

def _reverse(graph):
    r = {}
    for src in graph:
        for (dst,c) in graph[src].items():
            if dst in r:
                r[dst][src] = c
            else:
                r[dst] = { src : c }
    return r

def _getCycle(n,g,visited=set(),cycle=[]):
    visited.add(n)
    cycle += [n]
    if n not in g:
        return cycle
    for e in g[n]:
        if e not in visited:
            cycle = _getCycle(e,g,visited,cycle)
    return cycle

def _mergeCycles(cycle,G,RG,g,rg):
    allInEdges = []
    minInternal = None
    minInternalWeight = sys.maxint

    # find minimal internal edge weight
    for n in cycle:
        for e in RG[n]:
            if e in cycle:
                if minInternal is None or RG[n][e] < minInternalWeight:
                    minInternal = (n,e)
                    minInternalWeight = RG[n][e]
                    continue
            else:
                allInEdges.append((n,e))        

    # find the incoming edge with minimum modified cost
    minExternal = None
    minModifiedWeight = 0
    for s,t in allInEdges:
        u,v = rg[s].popitem()
        rg[s][u] = v
        w = RG[s][t] - (v - minInternalWeight)
        if minExternal is None or minModifiedWeight > w:
            minExternal = (s,t)
            minModifiedWeight = w

    u,w = rg[minExternal[0]].popitem()
    rem = (minExternal[0],u)
    rg[minExternal[0]].clear()
    if minExternal[1] in rg:
        rg[minExternal[1]][minExternal[0]] = w
    else:
        rg[minExternal[1]] = { minExternal[0] : w }
    if rem[1] in g:
        if rem[0] in g[rem[1]]:
            del g[rem[1]][rem[0]]
    if minExternal[1] in g:
        g[minExternal[1]][minExternal[0]] = w
    else:
        g[minExternal[1]] = { minExternal[0] : w }


def mst(root,G):


    RG = _reverse(G)
    if root in RG:
        RG[root] = {}
    g = {}
    for n in RG:
        if len(RG[n]) == 0:
            continue
        minimum = sys.maxint
        s,d = None,None
        for e in RG[n]:
            if RG[n][e] < minimum:
                minimum = RG[n][e]
                s,d = n,e
        if d in g:
            g[d][s] = RG[s][d]
        else:
            g[d] = { s : RG[s][d] }

    cycles = []
    visited = set()
    for n in g:
        if n not in visited:
            cycle = _getCycle(n,g,visited)
            cycles.append(cycle)

    rg = _reverse(g)
    for cycle in cycles:
        if root in cycle:
            continue
        _mergeCycles(cycle, G, RG, g, rg)

    return g


if __name__ == "__main__":
    try:
        filename = sys.argv[1]
        root = sys.argv[2]
    except IndexError:
        sys.stderr.write('no input and/or root node specified\n')
        sys.stderr.write('usage: python edmonds.py <file> <root>\n')
        sys.exit(1)

    prices,names = _input(filename)
    g = _load(prices,prices)
    h = mst(int(root),g)
    for s in h:
        for t in h[s]:
            print "%d-%d" % (s,t)