无法解决bfs实施中的错误

问题描述

我写了bfs来查找到其他每个节点的最短路径:

queue<int> q;
dist[s] = 0; // maintains the distance of vertices from s(source).
q.push(s);
while(!q.empty()){
    int src = q.front();
    q.pop();
    vis[src] = 1;          // visited array to keep track of nodes which have been visited
    
    for(int i=0; i<adj[src].size(); i++){ // adj is an adjacency list
        if(!vis[adj[src][i]]){
            q.push(adj[src][i]);
            dist[adj[src][i]] = 6+dist[src];
        }
    }
}

这会给某些未知的测试用例带来错误的响应和超时。 但是当我这样做时,它通过了所有测试用例:

queue<int> q;
dist[s] = 0;
vis[s] = 1;
q.push(s);
while(!q.empty()){
    int src = q.front();
    q.pop();
    
    for(int i=0; i<adj[src].size(); i++){
        if(!vis[adj[src][i]]){
            q.push(adj[src][i]);
            dist[adj[src][i]] = 6+dist[src];
            vis[adj[src][i]] = 1;
        }
    }
}

我不知道为什么会这样。

问题链接:https://www.hackerrank.com/challenges/bfsshortreach/problem

解决方法

我假设当您命名数组vis时,它代表is_node_visited,并且当且仅当节点is_node_visited[n]为真时,您希望n为真参观过。

这是问题所在。 BFS的正确概念是is_node_enqueued。当且仅当节点is_node_enqueued[n]曾经排队时,我们希望n为真。第二个代码正是这样做的(除了数组仍然令人困惑地称为vis)。

之所以需要is_node_enqueued而不是is_node_visited是因为您可能将同一节点排队两次。这是一个简单的例子,说明如何发生:

N1 -> N2
N1 -> N3
N2 -> N4
N3 -> N4

然后我们从N1开始'BFS'。

  • 访问N1时,它会排队N2N3
  • 访问N2时,它会排队N4
  • 访问N3时,尚未访问N4。

这是一个有趣的时刻-如果您仅在访问N4时才使用前者(即不正确的概念)来停止排队。 N4将再次入队。如果您在下面使用正确的概念,则该算法将注意到N4已入队,不会再次入队。

BFS的线性性能建立在一个节点仅被处理一次的前提之上。如果使用错误的版本,则会破坏该假设,因此您将不再在线性时间内处理图形。这就是为什么您超时的原因。

通常,用于诊断此类问题。一个有效的方法是生成一些随机输入。运行这两个程序,直到产生不同的结果,然后对导致问题的原因进行调试。

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...