我正在尝试实现一个java版本的Ford-Fulkerson。我使用wikipedia中的python实现作为基础:
class Edge(object):
def __init__(self, u, v, w):
self.source = u
self.sink = v
self.capacity = w
def __repr__(self):
return "%s->%s:%s" % (self.source, self.sink, self.capacity)
class FlowNetwork(object):
def __init__(self):
self.adj = {}
self.flow = {}
def add_vertex(self, vertex):
self.adj[vertex] = []
def get_edges(self, v):
return self.adj[v]
def add_edge(self, u, v, w=0):
if u == v:
raise ValueError("u == v")
edge = Edge(u,v,w)
redge = Edge(v,u,0)
edge.redge = redge
redge.redge = edge
self.adj[u].append(edge)
self.adj[v].append(redge)
self.flow[edge] = 0
self.flow[redge] = 0
def find_path(self, source, sink, path):
if source == sink:
return path
for edge in self.get_edges(source):
residual = edge.capacity - self.flow[edge]
if residual > 0 and edge not in path:
result = self.find_path( edge.sink, sink, path + [edge])
if result != None:
return result
def max_flow(self, source, sink):
path = self.find_path(source, sink, [])
while path != None:
residuals = [edge.capacity - self.flow[edge] for edge in path]
flow = min(residuals)
for edge in path:
self.flow[edge] += flow
self.flow[edge.redge] -= flow
path = self.find_path(source, sink, [])
return sum(self.flow[edge] for edge in self.get_edges(source))
这是我的java实现:
import org.junit.Test;
import java.util.*;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
public class MaxFlowTest {
@Test
public void maxFlowTest() {
FlowNetwork unit = new FlowNetwork(Arrays.asList(0, 1, 2, 3, 4, 5));
unit.addEdge(0, 1, 16);
unit.addEdge(0, 2, 13);
unit.addEdge(1, 3, 12);
unit.addEdge(1, 2, 10);
unit.addEdge(2, 1, 4);
unit.addEdge(2, 4, 14);
unit.addEdge(3, 2, 9);
unit.addEdge(4, 3, 7);
unit.addEdge(3, 5, 20);
unit.addEdge(4, 5, 4);
assertThat(unit.maxFlow(0, 5), is(23)); //algorithm incorrectly returning 7
}
}
class FlowNetwork {
Map<Integer, List<Edge>> edges = new HashMap<>();
Map<Edge, Integer> flow = new HashMap<>();
public FlowNetwork(List<Integer> vertices) {
vertices.forEach(v -> this.edges.put(v, new ArrayList<>()));
}
public Integer maxFlow(Integer source, Integer sink) {
List<Edge> path = null;
while (! (path=findAugmentedPath(source,sink,new ArrayList<>())).isEmpty()) {
int flow = path.stream().mapToInt(e -> e.capacity - this.flow.get(e)).min().getAsInt();
path.forEach(e -> {
this.flow.put(e, this.flow.get(e) + flow);
this.flow.put(e.reverseEdge, this.flow.get(e.reverseEdge) - flow);
});
}
return edges.get(source).stream().mapToInt(e -> flow.get(e)).sum();
}
List<Edge> findAugmentedPath(Integer source, Integer sink, List<Edge> pathSoFar) {
if (source == sink) {
return pathSoFar;
}
for (Edge neighbourEdge : this.edges.get(source)) {
int residual = neighbourEdge.capacity - flow.get(neighbourEdge);
if (residual > 0 && !pathSoFar.contains(neighbourEdge)) {
pathSoFar.add(neighbourEdge);
List<Edge> path = findAugmentedPath(neighbourEdge.b, sink, pathSoFar);
if (!path.isEmpty()) {
return path;
}
}
}
return Collections.emptyList();
}
public void addEdge(int source, int sink, int capacity) {
Edge edge = new Edge(source, sink, capacity);
Edge reverseEdge = new Edge(sink, source, 0);
edge.reverseEdge = reverseEdge;
reverseEdge.reverseEdge = edge;
this.edges.get(source).add(edge);
this.edges.get(sink).add(reverseEdge);
flow.put(edge, 0);
flow.put(reverseEdge, 0);
}
}
class Edge {
Integer capacity;
Edge reverseEdge;
int b;
int a;
public Edge(Integer a, Integer b, Integer capacity) {
this.a = a;
this.b = b;
this.capacity = capacity;
}
}
问题是java算法输出7,而不是测试用例中给出的示例的正确23。 代码运行时没有错误。 在调试算法时,我看不到任何不当行为。我不确定它是怎么回事。
我的问题是,任何人都可以帮助我理解它出错的方式和原因吗?
如果有助于在此pdf中提供示例图表的可视化表示:http://web.stanford.edu/class/cs97si/08-network-flow-problems.pdf
答案 0 :(得分:0)
我发现了问题...在调用findAugmentedPath时我没有创建pathSoFar的副本。糟糕!
Ansible_Hosts