【问题标题】:Topological order using bfs使用 bfs 的拓扑顺序
【发布时间】:2015-06-16 14:04:51
【问题描述】:

在 Sedgewick 和 Wayne 关于 java 算法的书中发现了以下问题:

4.2.19 拓扑排序和 BFS。 解释为什么以下算法不一定产生拓扑顺序:运行 BFS,并通过增加与顶点的距离来标记顶点各自的来源。

我试图证明它找到了一个反例。但是,每次我尝试时,我都会得到一个拓扑顺序。 我的意思是,我不明白为什么这不起作用:如果顶点的源在它之前,为什么我们没有拓扑顺序?

我认为为了证明这一点,我们需要找到它的来源之前的一个顶点,但我做不到。

谁有反例?提前致谢!

PS:这不是作业

@Edit: 我尝试过像 1

【问题讨论】:

标签: algorithm breadth-first-search topological-sort


【解决方案1】:

您不能使用 BFS,因为具有较高等级的节点可能具有较低等级的事件边。这是一个例子:

假设您在源 (A) 处启动 BFS。

使用您提出的算法,节点 D 将位于节点 C 之前,这显然不是拓扑顺序。你真的必须使用 DFS。

【讨论】:

  • 排名的定义是什么?我只知道树的等级。而且,如果 D 出现在 A 的邻接列表的第一个位置,D 可能会排在 C 之前,对吧?
  • Rank 可以认为是一个节点在 BFS 中处理的“级别”。 A 的排名为 1,B 和 D 的排名为 2,以此类推
  • @Giovanna 如果此解决方案对您有用,请您接受答案吗?这样其他人就会知道答案是正确的
【解决方案2】:

是的,您可以使用 BFS 进行拓扑排序。其实我记得有一次我的老师告诉我,如果问题可以通过 BFS 解决,千万不要选择 DFS 来解决。因为 BFS 的逻辑比 DFS 更简单,所以大多数时候您总是想要一个简单的问题解决方案。

您需要从 indegree0 的节点开始,这意味着没有其他节点直接指向它们。请务必先将这些节点添加到您的结果中。您可以使用 HashMap 来映射每个节点及其入度,并使用 BFS 中非常常见的队列来帮助您遍历。当您从队列中轮询一个节点时,其邻居的入度需要减少 1,这就像从图中删除该节点并删除该节点与其邻居之间的边一样。每次遇到度数为 0 的节点时,将它们提供给队列以便稍后检查其邻居并将它们添加到结果中。

  public ArrayList<DirectedGraphNode> topSort(ArrayList<DirectedGraphNode> graph) {

  ArrayList<DirectedGraphNode> result = new ArrayList<>();
    if (graph == null || graph.size() == 0) {
      return result;
    }
  Map<DirectedGraphNode, Integer> indegree = new HashMap<DirectedGraphNode, Integer>();
  Queue<DirectedGraphNode> queue = new LinkedList<DirectedGraphNode>();

//mapping node to its indegree to the HashMap, however these nodes
//have to be directed to by one other node, nodes whose indegree == 0
//would not be mapped.
  for (DirectedGraphNode DAGNode : graph){
      for (DirectedGraphNode nei : DAGNode.neighbors){
          if(indegree.containsKey(nei)){
              indegree.put(nei, indegree.get(nei) + 1);
          } else {
              indegree.put(nei, 1);
          }
      }
  }


//find all nodes with indegree == 0. They should be at starting positon in the result
  for (DirectedGraphNode GraphNode : graph) {
      if (!indegree.containsKey(GraphNode)){
          queue.offer(GraphNode);
          result.add(GraphNode);
      }
  }


//everytime we poll out a node from the queue, it means we delete it from the 
//graph, we will minus its neighbors indegree by one, this is the same meaning 
//as we delete the edge from the node to its neighbors.
  while (!queue.isEmpty()) {
      DirectedGraphNode temp = queue.poll();
      for (DirectedGraphNode neighbor : temp.neighbors){
          indegree.put(neighbor, indegree.get(neighbor) - 1);
          if (indegree.get(neighbor) == 0){
              result.add(neighbor);
              queue.offer(neighbor);
          }
      }
  }
  return result;
}

【讨论】:

    【解决方案3】:

    反例:

    A -> B
    A -> C
    B -> C
    

    A 开始的BFS 可以按A-B-CA-C-B 的顺序找到节点,但其中只有一个是拓扑排序。

    【讨论】:

      猜你喜欢
      • 2014-10-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-07-28
      相关资源
      最近更新 更多