【问题标题】:Find an edge using the Ford Fulkerson algorithm?使用 Ford Fulkerson 算法找到一条边?
【发布时间】:2012-01-06 18:30:47
【问题描述】:

我正在尝试用 C++ 实现 Ford Fulkerson 算法。

但是,我的find_edge 函数有问题。当我在my_alg 中调用此函数时,它会选择正确的边缘,然后在my_alg 中增加流。它选择右边缘并增加其流量 (flow),但是当我再次调用 find_edge 函数时,流量并未按应有的方式增加。

这导致我的算法无限循环。可能我对指针做错了什么。你可以在下面看到我的代码。

//An object of this class represents an edge in the graph.
class Edge
{
private:
    //Node *prev;

public:
    int flow;

    Edge(Node *firstNode, Node *secNode, unsigned inCost) {
        orgNode = firstNode;
        dstNode = secNode;
        bridge_capacity = inCost;
    }

    Edge() {
        flow=0;
    }
};

//An object of this class holds a vertex of the graph
class Node
{
public:
    Node *prev;

    vector<Edge>& getAdjNodeList() {
        return adjNodeList;
    }
};

Edge *find_edge(Graph *g,Node *from,Node *to) {
    vector<Edge> b=from->getAdjNodeList();
    for(int i=0;i<b.size();i++) {
        if(b[i].getDstNode()==to)
            return (&b[i]);
    }
    return NULL;
}

int my_alg(Graph *as,Node *source,Node *sink){
    Edge *find_edge();

    int max_flow=0;

    while(bfs(as,source,sink)) {
        Node *b=as->nodeList[num_isl];
        int inc=100000000;
        while(b->prev!=NULL) {
            Edge *bok=find_edge(as,b->prev,b);
            inc=min(inc,bok->get_bridge_capacity()-bok->flow);
            b=b->prev;
        }

        b=as->nodeList[num_isl];

        while(b->prev!=NULL){
            Edge *bok = find_edge(as,b->prev,b);
            bok->flow += inc;       // This is the place the flow is incremented
            bout << bok->flow;      // Here, everything is alright.
            bok = find_edge(as,b->prev,b);
            cout << bok->flow;      // However, this is is not the correct result.
        }
        max_flow+=inc;
    }
    return max_flow;
}

【问题讨论】:

  • 在my_alg的开头,你为什么要做“Edge *find_edge();” ?
  • 如果有帮助,我会收到此错误:错误 C2660: 'find_edge' : function does not take 3 parameters, but it is defined as : Edge *find_edge(Graph *g, Node *from , 节点 *to) , 三个参数
  • 实际上我忘记删除 my_alg 中的 *find_edge()。我在尝试解决问题时添加了这一行。但它并没有改变任何东西
  • 我没有收到任何错误,例如“find_edge”:函数不采用 3 个参数。
  • 要获得好的答案,最好将代码减少到问题明确需要的部分。没有多少人会通读你所有的 300 行代码。此外,请务必查看代码的格式 - 这次我为您做了一些缩进,一旦经过同行评审,就可以看到。但是,通常这应该是您的工作。

标签: c++ algorithm graph-theory flow ford-fulkerson


【解决方案1】:

我更彻底地查看了您的代码。为了帮助您以后自己跟踪问题,我将向您展示一个查找错误的示例过程。

如果您确实无法通过查看代码来找到问题,您可能需要删除所有混淆您对该问题的看法的内容。精简后的代码可能如下所示:

class Edge {
public:
    int flow;
};    

class Node {
private:
    vector<Edge> adjNodeList; // list of outgoing edges for this vertex

public:
    vector<Edge> & getAdjNodeList() {
        return adjNodeList;
    }

    void addAdjNode(Node* newAdj) {
        adjNodeList.push_back(Edge(newAdj));
    }
 };    


int main() {
    Node *node1 = new Node();
    Node *node2 = new Node();
    node1->addAdjNode(node2);

    vector<Edge> t = node1->getAdjNodeList();
    vector<Edge> f = node1->getAdjNodeList();
    t[0].flow = 11;

    cout << t[0] << endl;
    cout << f[0] << endl;
}

如果您运行此代码,您会注意到t[0]f[0] 并不相同。因为我只是复制了你代码的关键元素,原因应该还是一样的。

这里发生了什么?调用时

vector<Edge> t = node1->getAdjNodeList();

邻接列表是通过引用返回的,这应该让您获得对原始列表的引用 - 您应该能够更改它的元素,不是吗?但是,当将此引用分配给新分配的向量 t 时,会调用隐式复制构造函数,因此当您想要保存引用时,t 将包含您的向量的副本 (!)。

要解决此问题,您可以执行以下操作:

vector<Edge> & t = node1->getAdjNodeList();

保存引用但不创建新对象。

我只能假设为什么函数调用之间的指针碰巧是相同的:对象可能每次都被复制到同一个地方。此外,请注意您增加了不再存在的对象的值 - 副本在 find_edge-call 结束时被删除。

由于您没有自己追踪问题,因此需要一些时间来回答您的问题。如果你给出了上面的例子,我敢打赌你的解决方案会在几分钟内出现。鼓励您在堆栈溢出时提出您的问题 - 但是,大多数成员不愿意通过大量代码自己识别问题。这意味着,高质量的答案通常需要直截了当的问题。 (最后一段是为了在将来帮助你,但是可以在不改变问题的情况下减少它。

除此之外,我强烈建议您不要像现在这样使用您的对象。通过将所有内容作为引用传递并在对象外部进行所有更改,您基本上绕过了使面向对象编程如此强大的封装。例如,如果您刚刚将另一个函数 increaseFlow(Edge* to, int increment) 添加到您的 Node 并在对象中完成了所有操作,那将会更明智(并且不会给您带来问题)。

希望我能帮上忙。

【讨论】:

  • 非常感谢 Thilo。你说的对我很有帮助。我很感激你。
猜你喜欢
  • 1970-01-01
  • 2015-06-07
  • 2013-05-21
  • 1970-01-01
  • 1970-01-01
  • 2019-07-04
  • 2013-05-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多