Python 如何计算包含循环的有向图中的最大流量
我试图用Ford Fulkerson算法来寻找网络中的最大流量,它对非循环图非常有效,但是如果有一个循环,它将永远循环。下面是我用来查找最大流量的代码:Python 如何计算包含循环的有向图中的最大流量,python,algorithm,graph,network-flow,Python,Algorithm,Graph,Network Flow,我试图用Ford Fulkerson算法来寻找网络中的最大流量,它对非循环图非常有效,但是如果有一个循环,它将永远循环。下面是我用来查找最大流量的代码: class Edge (object): reverse = None def __init__ (self, u, v, w): self.source = u self.sink = v self.capacity = w self.flow = 0 cl
class Edge (object):
reverse = None
def __init__ (self, u, v, w):
self.source = u
self.sink = v
self.capacity = w
self.flow = 0
class FlowNetwork (object):
def __init__ (self, path):
rows = len (path)
cols = len (path[0])
self.graph = {self.vname (x, rows): [] for x in range (rows)}
for r in range (rows):
for c in range (cols):
if path[r][c] > 0:
u = self.vname (r, rows)
v = self.vname (c, rows)
edge = Edge (u, v, path[r][c])
reverse = Edge (v, u, 0)
edge.reverse = reverse
reverse.reverse = edge
self.graph[u].append (edge)
self.graph[v].append (reverse)
def vname (self, x, t):
return 's' if x == 0 else 't' if x == t - 1 else 'v' + str (x)
def dfs (self, source, sink):
queue = [[x] for x in self.graph[source]]
while queue:
path = queue.pop (0)
vertex = path[-1]
if vertex.sink == sink: return path
for edge in self.graph[vertex.sink]:
if edge.capacity - edge.flow > 0:
if edge not in path and edge.reverse not in path:
queue.append ([x for x in path] + [edge])
def maxFlow (self, source, sink):
path = self.dfs (source, sink)
while path != None:
flow = min ([edge.capacity - edge.flow for edge in path])
for edge in path:
edge.flow += flow
edge.reverse.flow -= flow
path = self.dfs (source, sink)
return sum (edge.flow for edge in self.graph[source])
例如,如果我使用上述程序求解以下网络:
它将无限期地运行,如何在这样的网络中找到最大流量
更新:
在上面的代码中,我忘记了在深度优先搜索dfs函数中跟踪访问的边,因此我将其修复如下:
def dfs (self, source, sink):
queue = [[x] for x in self.graph[source]]
visited = []
while queue:
path = queue.pop (0)
vertex = path[-1]
if vertex.sink == sink: return path
for edge in self.graph[vertex.sink]:
if edge not in visited and edge.capacity - edge.flow > 0:
if edge not in path and edge.reverse not in path:
queue.append ([x for x in path] + [edge])
visited.append (edge)
然而,它仍然无限期地循环。我还没有详细研究您的代码,但一下子看起来您的DFS不是一个合适的DFS。它需要一个“已访问集”以避免循环。您应该看看FF的一个变体(如Edmons Karp),它详细说明了用于查找扩充路径的方法。@Gene I修复了dfs函数,但由于某种原因,它仍然在反向边(s,t)上永远循环,这是为什么?可能是因为您没有考虑反向边列表?还要注意,为了避免增加渐进运行时间,您应该为访问集使用实数集,而不是列表。访问集应该包含顶点,而不是边。通常,您的代码看起来很奇怪,因为它们的边和顶点之间没有明确的区别(应该有)。这可能是错误的根源。我还没有详细研究过你的代码,但马上看来你的DFS不是一个合适的DFS。它需要一个“已访问集”以避免循环。您应该看看FF的一个变体(如Edmons Karp),它详细说明了用于查找扩充路径的方法。@Gene I修复了dfs函数,但由于某种原因,它仍然在反向边(s,t)上永远循环,这是为什么?可能是因为您没有考虑反向边列表?还要注意,为了避免增加渐进运行时间,您应该为访问集使用实数集,而不是列表。访问集应该包含顶点,而不是边。通常,您的代码看起来很奇怪,因为它们的边和顶点之间没有明确的区别(应该有)。这可能是错误的根源。