【问题标题】:DFS: Check if path exists between node A and node BDFS:检查节点 A 和节点 B 之间是否存在路径
【发布时间】:2022-01-05 04:41:29
【问题描述】:

在双向图中检查节点 A 和节点 B 之间是否存在路径。

我的代码不适用于某些输入(下面提供示例)。这个实现是正确的还是我遗漏了什么?

bool[] visited = null;
public bool ValidPath(int n, int[][] edges, int start, int end) {
    IList<int>[] adjacencyList = new List<int>[n];
    visited = new bool[n];
    
    // create adjacency list
    for(int i = 0; i < edges.Length; i++){
        int a = edges[i][0];
        int b = edges[i][1];
        
        if(adjacencyList[a] == null)
            adjacencyList[a] = new List<int>();
        adjacencyList[a].Add(b);
        
        if(adjacencyList[b] == null)
            adjacencyList[b] = new List<int>();
        adjacencyList[b].Add(a);            
    }
    
    return DFS(adjacencyList, start, end);
}

private bool DFS(IList<int>[] adjacencyList, int start, int end){
    if(start == end) return true;
    
    if(!visited[start]){
        visited[start] = true;
        foreach(var v in adjacencyList[start]){
            if(v == end) return true;
            if(!visited[v])
                DFS(adjacencyList, v, end);
        }
    }
    return false;
}

这适用于以下示例:

输入:n = 3,边 = [[0,1],[1,2],[2,0]],开始 = 0,结束 = 2 输出:真

输入:n = 6,边 = [[0,1],[0,2],[3,5],[5,4],[4,3]],开始 = 0,结束 = 5 输出:假

不适用于以下情况(预期返回值为真,但我得到假):

输入:10,边 = [[4,3],[1,4],[4,8],[1,7],[6,4],[4,2],[7,4 ],[4,0],[0,9],[5,4]], 开始 = 5, 结束 = 9

【问题讨论】:

  • 1.为什么用 BFS 标记问题? 2. 考虑添加 cmets 并使用有意义的名称而不是 a,b,n 以使代码更具可读性。
  • @c0der 1. 移除 BFS 标签 2. 从概念上解释需求。与此相关的示例和代码示例
  • if(!visited[v] &amp;&amp; DFS(adjacencyList, v, end)) return true;

标签: c# algorithm graph-theory depth-first-search


【解决方案1】:

该方法是正确的,唯一的问题是在递归DFS 中,您需要跟踪所有后续DFS 调用的结果。如果任何递归调用返回 true,则解决方案应返回 true(而不是直接返回 false)。这是 DFS 函数的略微修改版本:

private bool DFS(IList<int>[] adjacencyList, int start, int end){
  if(start == end) return true;

  bool status = false;
  if(!visited[start]){
    visited[start] = true;
    foreach(var v in adjacencyList[start]){
        if(v == end) {
            return true;
        }
        if(!visited[v]) {
            status = status || DFS(adjacencyList, v, end);
        }
    }
  }
  return status;
}

更新: 感谢 cmets 中的建议。如果任何相邻顶点的DFS 返回true,则该方法可以直接返回true(而不是使DFS 调用其他相邻顶点并保留status)。这给了我们DFS 的另一种变体:

private bool DFS(IList<int>[] adjacencyList, int start, int end){
  if (start == end) return true;

  bool status = false;
  if(!visited[start]){
    visited[start] = true;
    foreach(var v in adjacencyList[start]){
        if(v == end) {
            return true;
        }
        if(!visited[v] && DFS(adjacencyList, v, end)) {
            return true;
        }
    }
  }
  return status;
}

【讨论】:

  • 如果从DFS返回true就可以立即返回,而不用继续寻找更多路径。我会做类似if (DFS(...)) return true; 的事情,而不是更新这个status 变量。
  • 同意!这可能是另一种方式。
猜你喜欢
  • 2021-12-10
  • 1970-01-01
  • 2016-04-29
  • 2012-06-08
  • 1970-01-01
  • 2012-12-15
  • 1970-01-01
  • 2017-06-03
  • 1970-01-01
相关资源
最近更新 更多