如何找到图形扩充路径

时间:2011-04-21 19:06:22

标签: c++ graph

我正在尝试实施 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;
}

这是错误/不完整的,因为它返回了错误的结果。我想我正在伪造一些东西。

3 个答案:

答案 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)