使用 Ford Fulkerson 算法找到边缘?

发布于 2024-12-25 13:59:29 字数 1895 浏览 5 评论 0原文

我正在尝试用 C++ 实现福特富尔克森算法。

但是,我的 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;
}

I'm trying to implement the Ford Fulkerson Algorithm in C++.

However, I'm having trouble with my find_edge function. When I call this function in my_alg, it chooses the correct edge and then the flow is incremented in my_alg. It chooses the right edge and increment its flow (flow), but when I call the find_edge function again, the flow is not incremented as it should be.

This results in an endless loop of my algorithm. Probably I do something wrong with the pointers. You can see my code below.

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

雨后咖啡店 2025-01-01 13:59:29

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

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

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 调用结束时被删除。

由于您没有亲自找到问题所在,所以花了一些时间才回答您的问题。如果您给出了上面的示例,我敢打赌您的解决方案将在几分钟之内出现。我们鼓励您在堆栈溢出时提出您的问题 - 然而,大多数成员不愿意通过大量代码来自己识别问题。这意味着高质量的答案通常需要直接切中要点的问题。 (最后一段是为了将来为您提供帮助,但是,可以在不改变问题的情况下减少它)。

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

希望我能帮忙。

I had a more thorough look at your code. To help you track your problems down yourself in the future, I will show you a sample process of finding the error.

If you really can not find the problem by looking at the code, you may want to strip down everything that obfuscates your view on the problem. The reduced code could look like this:

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

If you would run this code, you would notice that t[0] and f[0] are not the same. As I just copied the crucial elements of your code, the reason should still be the same.

What is happening here? When calling

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

the adjacency list is returned by reference, which should leave you with a reference to the original list - you should be able to change it's elements, shouldn't you? However, when assigning this reference to the newly allocated vector t, the implicit copy constructor is called, thus t will contain a copy (!) of your vector while you wanted to save a reference.

To get around this problem, you could just have done the following:

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

which saves the reference and does not create a new object.

I can only assume why the pointers happened to be identical between calls to the function: The object probably was copied to the same place every time. Furthermore, note that you increased the value of an object that did not exist anymore - the copy was deleted with the end of the find_edge-call.

It took some time to give an answer to your question as you did not track the problem down yourself. If you had given the example above, I bet your solution would have been there within a matter of minutes. You are encouraged to raise your problems here at stack overflow - however, most members will not be willing to work through a lot of code to identify the problem themselves. That means, high quality answers usually require questions that directly come to the point. (The last paragraph was intended to help you in the future, however, it could be reduced without altering the question).

Apart from that, I would strongly encourage you not to use your objects the way you do. By passing everything as references and making all changes outside the object, you essentially bypass the encapsulation that makes object orientated programming that powerful. For example, it would be much wiser (and would not have given you your problem) if you just had added another function increaseFlow(Edge* to, int increment) to your Node and had done everything within the object.

Hope I could help.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文