C++算法:01BFS最短距离的原理和实现

简介: C++算法:01BFS最短距离的原理和实现

时间复杂度

O(n),n是边数。

使用前提

边的权只有两种:0,1。

典型场景

n个端点的无向图,编号范围[0,n)。Edges0表示{{n1,n2},...{n3,n4}}表示n1和n2,n3和n4之间有路联接。Edges1表示{{n1,n2},...{n3,n4}}表示n1和n2,n3和n4之间有损坏的路连接。要想让s和d之间至少有一条通道,最小需要维修多少条路。如果无法到达,请返回-1。可能有环,但无自环,重边,可能不联通。

解题思路

可以用类似上章的思路,没损害的路加到pre中,损坏的路加到que中。距离相等的点,谁先谁后无所谓。需要维修的路入队的时候不能计算最短距离,因为不一定是最短边。改在入队计算最短距离,第一层循环记录最短距离。

核心代码

class CBFS1
{
public:
    CBFS1(vector<vector<int>>& vNeiB0, vector<vector<int>>& vNeiB1, int s)
    {
        m_vDis.assign(vNeiB0.size(), -1);
        //m_vDis[s] = 0;
        queue<int> pre;
        pre.emplace(s);
        for (int i = 0; pre.size(); i++)
        {
            queue<int> dp;
            while (pre.size())
            {
                const int cur = pre.front();
                pre.pop();
                if (-1 != m_vDis[cur])
                {
                    continue;
                }
                m_vDis[cur] = i;
                for (const auto next : vNeiB0[cur])
                {
                    pre.emplace(next);
                }
                for (const auto next : vNeiB1[cur])
                {
                    dp.emplace(next);
                }
            }
            dp.swap(pre);
        }
    }
public:
    vector<int> m_vDis;
};

测试样例

#define CBFS CBFS1 
class CDebugBFS : public CBFS
{
public:
    using CBFS::CBFS;
    void Assert(const vector<int>& vDis)
    {
        for (int i = 0; i < vDis.size(); i++)
        {
            assert(vDis[i] == m_vDis[i]);
        }
    }
};
struct CDebugParam
{
    int n;
    vector<vector<int>> edges0;
    vector<vector<int>> edges1;
    int s;
    vector<int> dis;//答案
};
int main()
{
    vector<CDebugParam> params = { {1,{},{},0,{0}},{2,{},{},0,{0,-1}},{2,{{0,1}},{},0,{0,0}},{2,{},{{0,1}},0,{0,1}},
    {6,{}, { {0,1},{1,2},{1,3},{2,4},{4,5},{3,5}},0,{0,1,2,2,3,3} },
    {6,{{3,5}}, { {0,1},{1,2},{1,3},{2,4},{4,5}},0,{0,1,2,2,3,2} }
    };
    for (const auto& par : params)
    {
        auto vNeiB0 = EdgeToNeiBo(par.n, par.edges0);
        auto vNeiB1 = EdgeToNeiBo(par.n, par.edges1);
        CDebugBFS bfs(vNeiB0, vNeiB1,par.s);
        bfs.Assert(par.dis);
    }
}

类似场景

魔塔经典问题,砸墙需要一个锄头,没墙的地方可以随便移动,如果用尽可能少的锄头到达目的地。许多游戏经过箭塔附件时,会遭到箭塔攻击。如何已最小的损坏通过箭塔。

用双向队列优化

当前状态

操作

新状态

处理结束

首尾入队

一种最短距离

一种最短距离

出队

状态不变或变为空

队首入队

一种最短距离或两种最短距离

队尾入队

一种最短距离或两种最短距离

二种最短距离

出队

状态不变或变为一种最短距离

队首入队

两种最短距

队尾入队

两种最短距

class C01BFSDis
{
public:
    C01BFSDis(vector<vector<int>>& vNeiB0, vector<vector<int>>& vNeiB1, int s)
    {
        m_vDis.assign(vNeiB0.size(), -1);
        std::deque<std::pair<int,int>> que;
        que.emplace_back(s,0);
        while (que.size())
        {
            auto it = que.front();
            const int cur = it.first;
            const int dis = it.second;
            que.pop_front();
            if (-1 != m_vDis[cur])
            {
                continue;
            }
            m_vDis[cur] = it.second;
            for (const auto next : vNeiB0[cur])
            {
                if (-1 != m_vDis[next])
                {
                    continue;
                } 
                que.emplace_front(next,dis);
            }
            for (const auto next : vNeiB1[cur])
            {
                if (-1 != m_vDis[next])
                {
                    continue;
                }
                que.emplace_back(next, dis+1);
            }
        }
    }
public:
    vector<int> m_vDis;
};

下载

源码下载:

https://download.csdn.net/download/he_zhidan/88383828


其它

视频课程

如果你觉得复杂,想从简单的算法开始,可以学习我的视频课程。

https://edu.csdn.net/course/detail/38771

我的其它课程

https://edu.csdn.net/lecturer/6176

测试环境

win7 VS2019 C++17 或Win10 VS2022 Ck++17

相关下载

算法精讲《闻缺陷则喜算法册》doc版

https://download.csdn.net/download/he_zhidan/88348653

相关文章
|
9天前
|
存储 机器学习/深度学习 算法
第十五届蓝桥杯pb组国赛E题[马与象] (15分)BFS算法 详解
第十五届蓝桥杯pb组国赛E题[马与象] (15分)BFS算法 详解
16 3
|
8天前
|
自然语言处理 算法 搜索推荐
分词算法的基本原理及应用
分词算法的基本原理及应用
|
4天前
|
搜索推荐 算法 C++
|
4天前
|
存储 算法 Serverless
|
4天前
|
存储 算法 搜索推荐
|
5天前
|
算法 PHP
【php经典算法】冒泡排序,冒泡排序原理,冒泡排序执行逻辑,执行过程,执行结果 代码
【php经典算法】冒泡排序,冒泡排序原理,冒泡排序执行逻辑,执行过程,执行结果 代码
7 1
|
6天前
|
算法 安全 Java
Java中MD5加密算法的原理与实现详解
Java中MD5加密算法的原理与实现详解
|
11天前
|
算法 数据中心 C++
基于C++雪花算法工具类Snowflake -来自chatGPT
基于C++雪花算法工具类Snowflake -来自chatGPT
12 1
|
2天前
|
设计模式 JavaScript 算法
vue2 原理【详解】MVVM、响应式、模板编译、虚拟节点 vDom、diff 算法
vue2 原理【详解】MVVM、响应式、模板编译、虚拟节点 vDom、diff 算法
10 0