如何找到图增广路径
我正在尝试实现 Ford-Fulkerson 算法 来计算流网络中的最大流量。
该算法的一个步骤是找到一条从起始节点到结束节点(也称为汇点)且所有边上都具有可用容量的路径。
您能否建议一种简单易懂的方法来找到增强路径?
更新 #1:
我的 BFS 函数:
template <class T>
vector<Vertex<T> *> Graph<T>::bfs(T source) const {
vector<Vertex<T> *> path;
queue<Vertex<T> *> q;
Vertex<T> * v = getVertex(source);
q.push(v);
v->visited = true;
while (!q.empty()) {
Vertex<T> *v1 = q.front();
q.pop();
path.push_back(v1);
typename vector<Edge<T> >::iterator it = v1->adj.begin();
typename vector<Edge<T> >::iterator ite = v1->adj.end();
for (; it!=ite; it++) {
Vertex<T> *d = it->dest;
if (d->visited == false) {
d->visited = true;
q.push(d);
}
}
}
return path;
}
它是错误/不完整的,因为它返回了错误的结果。我想我忘记了什么。
I'm trying to implement the Ford-Fulkerson algorithm to compute the maximum flow in a flow network.
One step of the algorithm is to find a path from the start node to the end node (also know as sink) with available capacity on all edges.
Could you suggest a easy and understandable way to find the augmenting path?
UPDATE #1:
My BFS function:
template <class T>
vector<Vertex<T> *> Graph<T>::bfs(T source) const {
vector<Vertex<T> *> path;
queue<Vertex<T> *> q;
Vertex<T> * v = getVertex(source);
q.push(v);
v->visited = true;
while (!q.empty()) {
Vertex<T> *v1 = q.front();
q.pop();
path.push_back(v1);
typename vector<Edge<T> >::iterator it = v1->adj.begin();
typename vector<Edge<T> >::iterator ite = v1->adj.end();
for (; it!=ite; it++) {
Vertex<T> *d = it->dest;
if (d->visited == false) {
d->visited = true;
q.push(d);
}
}
}
return path;
}
It's wrong/incomplete since it's returning wrong results. I think I'm forgeting something.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
请阅读此处。基本上使用Breadth-first_search。
编辑:
path.push_back(v1);
位于错误的位置。您将把图形的所有顶点添加到路径中。正确的方法是为每个节点存储前驱节点。这样你就可以恢复找到的路径。您还可以在到达接收器时中断while
子句。Read here. Basically use Breadth-first_search.
Edit:
path.push_back(v1);
is at the wrong place. You will add all vertices of the graph to the path. The correct way is to store for each node which is the predecessor node. This way you can restore the found path. Also you can break thewhile
clause when you reach the sink.在不了解底层数据结构的情况下给你明确的建议有点困难。通常当你处理流时,你会有一个有向图。我将假设这是我的答案。
现在我看到了一些主要问题和一个小评论:
在这种情况下,列表可能是更好的选择,因为向量仅摊销恒定的插入和删除时间,而列表确实是恒定的。 (假设您指的是 STL 容器)- 这是次要评论;)
对于 BFS,您有两个选择:要么保存所有路径,要么在访问每个顶点后保存其前趋。您只需保存必须访问的顶点即可。这样,我不知道一旦到达水槽,您将如何重建完整的路径。
初始化对我来说似乎很好。
在这里,您获取当前所在顶点的邻接列表。但请记住,增广路径之所以称为增广,是因为您可以向前(如果还有剩余容量,因此流过该边的电流小于该边的容量)或向后(如果流过该边的电流)遍历一条边。边缘大于 0)。您只需获取图中前进的所有边并访问它们即可。这是“正常”BFS,而不是适应最大流问题中使用的不同图结构的 BFS。
(为了完整性:你可以将你的网络与当前流结合起来,并从中创建一个新图(我知道这个是辅助网络),它准确地代表了这个结构。在这种情况下,你的 BFS 会工作得很好。如果你正在做现在,我想看看辅助网络的例程计算)。
除了我已经提到的几点之外,这部分对我来说看起来不错。因此 - 保存前趋,检查路径是否对最大流量有帮助(有剩余容量)并检查向后弧。
再看看您在路径变量中收集的内容。实际上,您按照访问顺序将 BFS 访问的所有顶点保存在其中。但是,您需要这些顶点的子集来提供正确的路径。
最后评论:对于 Ford-Fulkerson,在执行 BFS 时直接计算可以在当前路径上增加流量的值可能是一个聪明的主意。这样您就不需要再次访问边缘。当然,您可以在使用尚未保存的前辈收集路径的同时执行此操作。
我不会给您完整的工作代码示例,因为我认为这是家庭作业,您应该学习一些东西而不是获得完成的代码。
It is a bit difficult to give you clear advice without knowing the underlying data structures. Usually when you deal with flows, you have a digraph. I will assume this for my answer.
Now I see a few major problems and one minor remark:
A list might in this case be a better option, as vectors have only amortized constant insertion and removal time, while lists do really constant. (Assuming you are referring to the STL-Containers) - this was the minor remark ;)
For BFS, you have two options: Either you save all paths, or you save the predecessor for each vertex once you visit it. You just save the vertices you have to visit. This way I do not see how you will be able to reconstruct a full path once you reach the sink.
Initialization seems fine to me.
Here you take the adjacency list of the vertex you currently are at. Remember, though, that augmenting paths are called augmenting because you can traverse an edge either forward (if there is capacity left, thus the current flow over this edge is less than the capacity of the edge) or backward (if the current flow over this edge is greater 0). You are just taking all edges that go forward in the graph and visit them. This is "normal" BFS, not BFS adapted to the differing graph structure used in max-flow-problems.
(For completeness: You could take your network together with the current flow and create a new graph from this (I know this one as auxiliary network) which is representing exactly this structure. In this case your BFS would work fine. If you are doing this right now, I would like to see the routine computing the auxiliary network).
That part looks fine for me, except the points I already mentioned. So - save predecessors, check whether a path is helpful for the max flow (has capacity left) and also check backward arcs.
Have another look at what you are collecting in your path variable. You actually save all vertices BFS visits in there in the order they are visited. However, you want a subset of these vertices that give the correct path.
Last remark: For Ford-Fulkerson, it might be a clever idea to compute the value you can increment the flow with on the current path directly while doing BFS. This way you do not need to visit the edges once again. Of course, you could do this while collecting the path using the not yet saved predecessors.
I will not give you a complete working code sample, as I assume this is homework and you are supposed to learn something rather than get finished code.
看一下源代码:这里是 http://aduni.org/courses /algorithms/courseware/handouts/Reciation_09.html
Have a look at source code: here it is http://aduni.org/courses/algorithms/courseware/handouts/Reciation_09.html