如何在图中找到从一个节点到另一个节点的路径

时间:2019-05-27 15:20:01

标签: c++ graph-theory depth-first-search breadth-first-search

我看过DFS和BFS的基本代码,我以为我理解它们,但实际上,我只了解基本代码的功能(访问图的所有节点)。 我要解决的问题是在有向图中找到一个循环并打印路径。我意识到我并不真正了解bfs和dfs。我开始在线搜索如何使用bfs / dfs查找从一个节点到另一个节点的路径,但是我发现并没有太大帮助。

任何人都可以给我一些链接,认为这些链接可以帮助我理解如何使用bfs / dfs查找节点之间的路径,或者只是给我一些建议?

1 个答案:

答案 0 :(得分:1)

对于极客,我将看看极客上的东西。 DFS和BFS的常规信息:

DFS:https://www.geeksforgeeks.org/depth-first-search-or-dfs-for-a-graph/

BFS:https://www.geeksforgeeks.org/breadth-first-search-or-bfs-for-a-graph/

对于周期:

BFS:https://www.geeksforgeeks.org/detect-cycle-in-a-directed-graph-using-bfs/

DFS:https://www.geeksforgeeks.org/detect-cycle-in-a-graph/

使用DFS的周期摘要:

  • 仅当图形中存在后边缘(由节点到其自身的边缘(自环)或其在DFS生成的树中的祖先之一的边缘)中时,图形中才存在一个循环)

  • 检测后边缘:

    • 保持跟踪递归堆栈中当前用于DFS遍历的顶点(即已检查/遍历的顶点)
    • 如果到达递归堆栈中已经存在的顶点,则树中会有一个循环

使用BFS的周期摘要:

步骤1:为图形中存在的每个顶点计算入度(传入边数),并将访问节点的数量初始化为0。

第2步:选取度数为0的所有顶点并将其添加到队列中(入队操作)

第3步:从队列中删除一个顶点(出队操作),然后。

已访问节点的计数增加1。 将其所有相邻节点的度数减少1。 如果将相邻节点的度降为零,则将其添加到队列中。

第4步:重复第3步,直到队列为空。

第5步:如果访问的节点数不等于图中具有循环次数的节点数,否则为非。

查找节点的度数

使用数组跟踪所有节点的度数

pseudo两种计算度数的方法:

  1. 遍历边缘数组,只需将目标节点的计数器增加1

       for each node in Nodes
    
           indegree[node] = 0;
    
       for each edge(src,dest) in Edges
    
           indegree[dest]++
    
  2. 遍历每个节点的列表,然后将与其连接的所有节点的入度递增1。

       for each node in Nodes
          If (list[node].size()!=0) then
          for each dest in list
            indegree[dest]++;
    

使用DFS在有向图中打印周期:(来源:https://www.careercup.com/question?id=5752609117831168

   public void printGraphCycles(Graph graph) {
    HashSet<Vertex> visited = new HashSet<>();
    HashSet<Vertex> candidates = new HashSet<>();
    for(Vertex vertex : graph.vertexs()){
        if(! visited.contains(vertex) && !candidates.contains(vertex))
            DFS(graph, vertex, visited, candidates);
    }
}

   public void DFS(Graph graph, Vertex vertex, HashSet<Vertex> visited, HashSet<Vertex> candidates) {
   /*
    1 ---] 2
    ]     /] \
    |    / |  ]
    |   /  |   3
    |  /   |  /
    | [    | [
    5 ----] 4
     */
    candidates.add(vertex);
    for(Vertex adj : graph.adj(vertex)) {

        if(candidates.contains(adj)) { 
            // visited nodes may need to revisit to build the cycle
            // so don't put visited.contains(adj) on the if condition.
            // an example is node 4
            // found cycle
            printCycle(vertex, adj);
        } else {
            adj.setParent(vertex); // build the trace back
            DFS(graph, adj, visited, candidates);
        }
    }
    candidates.remove(vertex);
    visited.add(vertex);
}