【问题标题】:unable to resolve the error in bfs implementation无法解决 bfs 实现中的错误
【发布时间】:2020-09-02 18:57:18
【问题描述】:

我已经写了 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

【问题讨论】:

  • 在我看来,您的问题并没有说明您为尝试诊断问题所做的工作,您只是提到“在某些情况下”,但不清楚您在说什么情况关于 - 可能是您不知道那是什么情况 - 即使这样,最好让我们知道“在某些未知的测试用例上它失败了”,而不是只说在某些情况下。

标签: c++ graph-algorithm breadth-first-search


【解决方案1】:

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

这就是问题所在。 BFS 的正确概念是is_node_enqueued。当且仅当节点 n 曾经入队时,我们希望 is_node_enqueued[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 的线性性能建立在一个节点只被处理一次的前提之上。如果我们使用不正确的版本,我们就会打破这个假设,因此您不再以线性时间处理图形。这就是为什么你会超时。

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

【讨论】:

  • 谢谢。实际上失败的测试用例是无法手动处理的,我想不出这个测试用例。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-06-28
  • 1970-01-01
  • 1970-01-01
  • 2018-01-05
  • 2013-03-27
  • 2013-10-23
  • 2018-06-05
相关资源
最近更新 更多