如何找到一个图增广路径

How to find a graph augmenting path

本文关键字:一个 路径 何找      更新时间:2023-10-16

我正在尝试实现Ford-Fulkerson算法来计算流网络中的最大流量。

算法的一个步骤是找到一条从开始节点到结束节点(也称为sink)的路径,所有边都有可用容量。

你能建议一个简单易懂的方法来找到扩展路径吗?

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;
}

返回的结果是错误的/不完整的。我想我忘了什么。

点击此处阅读。基本使用width -firstrongearch。

编辑:path.push_back(v1);在错误的地方。你将把图的所有顶点都添加到路径上。正确的方法是为每个节点存储前身节点。这样就可以恢复找到的路径。当你到达水槽时,你也可以打破while条款。

if (d->visited == false) {
    d->visited = true;
    q.push(d);
    predecessor[d] = v1;
}

在不了解底层数据结构的情况下,很难给出明确的建议。通常当你处理流的时候,你有一个有向图。我假设这是我的答案。现在我看到了几个主要问题和一个小问题:

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;

再看一下您在path变量中收集的内容。实际上你把BFS访问过的所有顶点按照访问的顺序保存在那里。但是,您需要这些顶点的子集给出正确的路径。

最后一句话:对于Ford-Fulkerson来说,在执行BFS时直接计算当前路径上可以增加的流的值可能是一个聪明的主意。这样你就不需要再次访问边缘了。当然,您可以在使用尚未保存的前辈收集路径时执行此操作。

我不会给你一个完整的工作代码示例,因为我认为这是家庭作业,你应该学习一些东西,而不是完成代码。

查看源代码:http://aduni.org/courses/algorithms/courseware/handouts/Reciation_09.html

相关文章: