我正在尝试实施 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;
}
这是错误/不完整的,因为它返回了错误的结果。我想我正在伪造一些东西。
答案 0 :(得分:3)
阅读here。基本上使用Breadth-first_search。
修改:path.push_back(v1);
位置错误。您将图表的所有顶点添加到路径中。正确的方法是为每个节点存储前一个节点。这样您就可以恢复找到的路径。您也可以在到达接收器时中断while
子句。
if (d->visited == false) {
d->visited = true;
q.push(d);
predecessor[d] = v1;
}
答案 1 :(得分:1)
在不了解基础数据结构的情况下,向您提供明确的建议有点困难。通常当你处理流程时,你有一个有向图。我会假设这是我的答案。 现在我看到一些主要问题和一个小问题:
template <class T>
vector<Vertex<T> *> Graph<T>::bfs(T source) const {
vector<Vertex<T> *> path;
在这种情况下,列表可能是更好的选项,因为向量只分摊了常量插入和删除时间,而列表确实是常量。 (假设你指的是STL-Containers) - 这是次要的评论;)
queue<Vertex<T> *> q;
对于BFS,您有两个选择:保存所有路径,或者在访问每个顶点时保存前一个路径。您只需保存您必须访问的顶点。这样,一旦你到达接收器,我就看不出你将如何重建完整的路径。
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();
在这里,您可以获取当前所在顶点的邻接列表。但请记住,扩充路径称为扩充路径,因为您可以向前移动边缘(如果有剩余容量,因此此边缘上的电流小于边缘容量)或向后移动(如果当前流过此边缘)边缘更大0)。您只需要在图表中前进所有边缘并访问它们。这是“正常”BFS,而不适用于最大流量问题中使用的不同图形结构的BFS。
(为了完整性:您可以将您的网络与当前流一起创建一个新的图形(我知道这个作为辅助网络),它正好代表了这种结构。在这种情况下,您的BFS可以正常工作。你现在正在这样做,我希望看到常规计算辅助网络。)
for (; it!=ite; it++) {
Vertex<T> *d = it->dest;
if (d->visited == false) {
d->visited = true;
q.push(d);
}
}
}
除了我已经提到的观点之外,那部分看起来不错。因此 - 保存前任,检查路径是否有助于最大流量(剩余容量)并检查反向弧。
return path;
再看看你在路径变量中收集的内容。实际上,您按照访问顺序将所有顶点BFS访问保存在那里。但是,您需要这些顶点的子集来提供正确的路径。
最后评论:对于Ford-Fulkerson来说,计算可以在执行BFS时直接在当前路径上增加流量的值可能是一个聪明的主意。这样您就不需要再次访问边缘。当然,您可以在使用尚未保存的前辈收集路径时执行此操作。
我不会给你一个完整的工作代码示例,因为我认为这是作业,你应该学习一些东西而不是完成代码。
答案 2 :(得分:0)