双端队列广搜

时间复杂度;

  • 每次从队列中取出队头为 $O(1)$
  • 整体时间复杂度为线性的,即 $O(n + m)$

适用场景

  • 边权仅为0或1的图中

算法模板

(整体思路类似堆优化 $dijkstra$ 算法)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
void bfs()
{
memset(dist, 0x3f, sizeof dist);
memset(st, 0, sizeof st);
dist[1] = 0;
q.push_front(1);

while(q.size())
{
// 每次取出队头,时间复杂度O(1)
auto t = q.front();
q.pop_front();

if(st[t]) continue;
st[t] = true;

for (int i = h[t]; ~i; i = ne[i])
{
int j = e[i];
if(dist[j] > dist[t] + w[i])
{
dist[j] = dist[t] + w[i];
if(!v) q.push_front(j);
else q.push_back(j);
}
}
}
}

算法证明:

  • 类似堆优化 $dijkstra$ 算法,因为边权只有0和1,可以将0插入队头,1插入队尾,可以保证单调性的同时,将从优先队列中取出最小值的 $O(logm)$ 的步骤,优化为只取出队头的 $O(1)$ 操作,从而将时间复杂度降低为线性