跳转至

0-1 BFS

what

边权值为可能有,也可能没有(由于 BFS 适用于权值为 1 的图,所以一般权值是 0 或 1),或者能够转化为这种边权值的最短路问题。

例如在走迷宫问题中,你可以花 1 个金币走 5 步,也可以不花金币走 1 步,这就可以用 0-1 BFS 解决。

01 BFS,又称双端队列 BFS,是一种仅适用于边权为 0/1 的情况(也即,存在或不存在)。

01 BFS 一般使用双端队列 deque 解决。

why

01 BFS 使用“0先1后”的优化方法来保证队列内有序。

也即:

  • 若选择边权为 0 的边,则将结果储存在双端队列的前方。
  • 若选择边权为 1 的边,则将结果储存在双端队列的后方。

01 BFS 具备着“第一次到某个点所需要的代价就是这个点的最小代价”的性质

有序性的证明

证明:

初始时队列仅有一个元素 0,队列有序。

对于每一次操作:

我们记每一次操作时的队首为 x,取出后队列有序,且仅含 x,x+1。(可以试着去证明,这里默认都知道。)

  • 选择 0,将 x 放入队首。
  • 选择 1,将 x+1 放入队尾。

显然,此时队列里仅含 x,x+1 这两种元素,队列有序。

how

vector<int> d(n, INF);
d[s] = 0;
deque<int> q;
q.push_front(s);
while (!q.empty()) {
    int v = q.front();
    q.pop_front();
    for (auto edge : adj[v]) {
        int u = edge.first;
        int w = edge.second;
        if (d[v] + w < d[u]) {
            d[u] = d[v] + w;
            if (w == 1)
                q.push_back(u);
            else
                q.push_front(u);
        }
    }
}

参考