【问题标题】:Finding a single path in a graph using dfs使用 dfs 在图中查找单个路径
【发布时间】:2014-12-17 20:17:20
【问题描述】:

我目前正在尝试在从源到接收器的图中找到一条路径。我正在尝试使用 dfs 实现一种方法来实现这一点。但是,我似乎无法弄清楚如何制作停止递归的方法。例如,我有这个图(矩阵形式)

0 1 1 0

0 0 0 1

0 0 0 1

0 0 0 0

所以我有一条从节点 0(源)到节点 1 和 2 的边,然后有一条从 1 和 2 到 3(接收器)的边。我想要的路径是 0>1>3,而不是我得到 0>1>3>2>3。一旦找到到接收器的路径,如何使递归停止?

这里是方法的代码:

public void dfsPath(int i) {

    boolean[] visited = new boolean[this.edgeCapacities.length];
    visited[i] = true;
    this.path.add(i); //Integer ArrayList containing the nodes in the path

            //loop through all of the nodes in the matrix to find adjacency
            for (int j = 0; j < this.edgeCapacities.length; j++) {
                //check if edge exists and node has not been visited
                if (this.edgeCapacities[i][j] != 0 && !visited[j]) {
                    //here is the problem, i want the recursion to stop once the sink is found
                    //it does not work however.
                    if(j == this.sink) {
                        visited[j] = true;
                        this.path.add(j);
                        return;
                    } else {
                        //recursion
                        dfsPath(j);
                    }
                }
        }

任何帮助将不胜感激。提前致谢。

【问题讨论】:

  • 您的 dfs 算法似乎已损坏。见this link
  • @Everv0id 我看不到问题所在。解释一下?

标签: java recursion matrix path depth-first-search


【解决方案1】:

您的 DFS 算法似乎有几个问题:

  • 通过在每个递归调用中创建一个新的visited 列表,它始终只包含当前节点
  • 您只是将节点添加到 this.path,但绝不会删除未达到目标的节点
  • 你永远不会检查你的递归​​调用是否达到了目标,从而将更多节点添加到完美的路径中

要解决这个问题,您应该在方法结束时从this.path 中删除当前节点,即在没有找到路径的情况下。此外,您可以删除 visited 数组并检查下一个节点是否已经在路径中。这不是那么快,但应该足以满足您的情况并使代码不那么复杂。此外,该方法应根据是否找到路径返回truefalse

试试这个(未经测试,但应该工作)。

public boolean dfsPath(int i) {
    this.path.add(i); // add current node to path
    if (i == this.sink) {
        return true; // if current node is sink, return true
                     // this.path contains nodes from source to sink
    }
    for (int j = 0; j < this.edgeCapacities.length; j++) {
        if (this.edgeCapacities[i][j] != 0 && ! this.path.contains(j)) {
            if (dfsPath(j)) {
                return true; // found a path -> search no further
            }
        }
    }
    this.path.remove(this.path.size() - 1); // pop last node
    return false; // no path found
}

请注意,我还将sink-check 移出循环。这纯粹是一个口味问题,但它使代码更简单一些,因为您不必将sink 节点单独添加到路径中。

【讨论】:

  • 非常感谢!经过几次调整,它就完美运行了!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-04-05
  • 2012-12-15
  • 1970-01-01
  • 1970-01-01
  • 2012-11-27
  • 1970-01-01
相关资源
最近更新 更多