首页 > 其他 > 详细

【B2B】01-BFS

时间:2019-11-06 09:50:18      阅读:215      评论:0      收藏:0      [点我收藏+]

纠正我对 01-BFS 问题的错误认识。

我一直以为对于 01-BFS,每次点 $u$ 出队时,对于 $u$ 的邻接边表中的边,只要先松弛边权为 0 的边再松弛边权为 1 的边就能保证每个点只入队一次。最近我发现我错了,例子:
技术分享图片

按照上述做法,入队序列是 1, 2, 3, 4, 5, 4, 5。
就算用一个数组标记点是否在队列中也没法解决这个问题,看下个例子:
技术分享图片

出入队序列是
+1, -1, +2, +3, -2, +4, +5, -3, -4, -5, +4, -4
可见 4 号点入队两次。

01-BFS 的正确做法是用双端队列代替普通队列。每次点 $u$ 出队时,对于 $u$ 的邻接边表中的能够被松弛的有向边 $(u, v)$,若 $(u,v)$ 权值是 0,则将 $v$ 放到队首,否则将 $v$ 放到队尾。

代码:

const int max_n = 5000;
vector<int> dis(max_n, INT_MAX);
vector<pair<int,int>> g(max_n);

void bfs(int s) {
    dis[s] = 0;
    deque<int> que;
    que.push(s);
    while (!que.empty()) {
        auto u = que.front();
        que.pop_front();
        for (auto& e, g[u]) {
            if (dis[u] + e.second < dis[e.first]) {
                dis[e.first] = dis[u] + e.second;
                if (e.second == 0) {
                    que.push_front(e.first);
                } else {
                    que.push_back(e.first);
                }
            }
        }
    }
} 

【B2B】01-BFS

原文:https://www.cnblogs.com/Patt/p/11802567.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!