C++算法:多源BFS

多源BFS

1.01矩阵

对于多源最短路问题,如果用单源最短路解决,即把每个源点进行一次BFS,显然是会超时超内存的。解决多源最短路,把所有源点当作一个超级源点并把所有源点一起入队列,再用BFS。

对于本题,可以创建距离数组dist,把dist置为-1,表示未访问过,省去了visited数组。如果以1为源点进行BFS,得到的距离难以分辨是哪个1的,采用正难则反的思想,以0为源点进行BFS,每扩一次,扩展到的新元素为扩展源点+1。

cpp 复制代码
class Solution
{
    int dx[4] = { 0,0,1,-1 };
    int dy[4] = { 1,-1,0,0 };
    int m = 0, n = 0;
public:
    vector<vector<int>> updateMatrix(vector<vector<int>>& mat)
    {
        m = mat.size(), n = mat[0].size();
        vector<vector<int>> dist(m, vector<int>(n, -1));
        queue<pair<int, int>> q;
        for (int i = 0;i < m;i++)
        {
            for (int j = 0;j < n;j++)
            {
                if (mat[i][j] == 0)
                {
                    dist[i][j] = 0;
                    q.push({ i,j });
                }
            }
        }
        while (!q.empty())
        {
            auto [a, b] = q.front();
            q.pop();
            for (int i = 0;i < 4;i++)
            {
                int x = a + dx[i], y = b + dy[i];
                if (x >= 0 && x < m && y >= 0 && y < n && dist[x][y] == -1)
                {
                    dist[x][y] = dist[a][b] + 1;
                    q.push({ x,y });
                }
            }
        }
        return dist;
    }
};

2.飞地的数量

与题目130被围绕的区域类似,采用正难则反的思想,先遍历grid的4条边,把其中为1的元素都加入队列,进行多源BFS,得到所有元素为1且挨着边的连通块,在标记数组中对应标记。最后遍历grid,如果gridi j为1且visi j为0,则计数。

cpp 复制代码
class Solution
{
    int dx[4] = { 0,0,1,-1 };
    int dy[4] = { 1,-1,0,0 };
public:
    int numEnclaves(vector<vector<int>>& grid)
    {
        int m = grid.size(), n = grid[0].size();
        vector<vector<bool>> vis(m, vector<bool>(n, 0));
        queue<pair<int, int>> q;
        for (int j = 0;j < n;j++)
        {
            if (grid[0][j] == 1)
            {
                grid[0][j] = 2;
                q.push({ 0,j });
                vis[0][j] = 1;
            }
            if (grid[m - 1][j] == 1)
            {
                grid[m - 1][j] = 2;
                q.push({ m - 1,j });
                vis[m - 1][j] = 1;
            }
        }
        for (int i = 0;i < m;i++)
        {
            if (grid[i][0] == 1)
            {
                grid[i][0] = 2;
                q.push({ i,0 });
                vis[i][0] = 1;
            }
            if (grid[i][n - 1] == 1)
            {
                grid[i][n - 1] = 2;
                q.push({ i,n - 1 });
                vis[i][n - 1] = 1;
            }
        }

        while (!q.empty())
        {
            auto [a, b] = q.front();
            q.pop();
            for (int i = 0;i < 4;i++)
            {
                int x = a + dx[i], y = b + dy[i];
                if (x >= 0 && x < m && y >= 0 && y < n && grid[x][y] == 1 && !vis[x][y])
                {
                    vis[x][y] = 1;
                    q.push({ x,y });
                }
            }
        }
        int ret = 0;
        for (int i = 1;i < m - 1;i++)
            for (int j = 1;j < n - 1;j++)
                if (grid[i][j] == 1 && !vis[i][j])
                    ret++;
        return ret;
    }
};

3.地图中的最高点

使用多源BFS,把所有水域当作一个源点,进行BFS找最远陆地,仿照前面的题目01矩阵即可,发现代码也是几乎一样的。

cpp 复制代码
class Solution
{
    int dx[4] = { 0,0,1,-1 };
    int dy[4] = { 1,-1,0,0 };
public:
    vector<vector<int>> highestPeak(vector<vector<int>>& isWater)
    {
        int m = isWater.size(), n = isWater[0].size();
        vector<vector<int>> height(m, vector<int>(n, -1));
        queue<pair<int, int>> q;
        for (int i = 0;i < m;i++)
            for (int j = 0;j < n;j++)
                if (isWater[i][j])
                {
                    height[i][j] = 0;
                    q.push({ i,j });
                }
        while (!q.empty())
        {
            auto [a, b] = q.front();
            q.pop();
            for (int i = 0;i < 4;i++)
            {
                int x = a + dx[i], y = b + dy[i];
                if (x >= 0 && x < m && y >= 0 && y < n && height[x][y] == -1)
                {
                    height[x][y] = height[a][b] + 1;
                    q.push({ x,y });
                }
            }
        }
        return height;
    }
};

4.地图分析

用多源BFS,把所有陆地方格当作一个源点,进行BFS找最远海洋方格,仿照题目01矩阵使用dist数组。因为方格扩展时是同行或同列扩展一层,distx y = dista b + abs(a-x) + abs(b-y) 等价于 distx y = dista b + 1。

cpp 复制代码
class Solution4
{
    int dx[4] = { 0,0,1,-1 };
    int dy[4] = { 1,-1,0,0 };
public:
    int maxDistance(vector<vector<int>>& grid)
    {
        int m = grid.size(), n = grid[0].size();
        vector<vector<int>> dist(m, vector<int>(n, -1));
        queue<pair<int, int>> q;
        for (int i = 0;i < m;i++)
            for (int j = 0;j < n;j++)
                if (grid[i][j] == 1)
                {
                    dist[i][j] = 0;
                    q.push({ i,j });
                }
        int ret = -1;
        while (!q.empty())
        {
            auto [a, b] = q.front();
            q.pop();
            for (int i = 0;i < 4;i++)
            {
                int x = a + dx[i], y = b + dy[i];
                if (x >= 0 && x < m && y >= 0 && y < n && dist[x][y] == -1)
                {
                    dist[x][y] = dist[a][b] + 1;
                    ret = max(ret, dist[x][y]);
                    q.push({ x,y });
                }
            }
        }
        return ret;
    }
};
相关推荐
AC赳赳老秦9 分钟前
采集行为合规自检:OpenClaw 自动校验 robots 协议与采集频率,规避违规采集风险
java·开发语言·c++·python·php·deepseek·openclaw
无名猿29 分钟前
C++ 查找算法:std::find 与容器成员 find 的性能差距
c++·性能优化·stl·标准库
程序猿编码1 小时前
工业视觉多任务方案:可编程梯度信息视觉框架,训练评估 + C++ 部署完整实战
开发语言·c++·视觉·推理引擎
朝朝辞暮i2 小时前
C++ 第 21 课:struct —— 把一组相关数据打包在一起
开发语言·c++·算法
青梅橘子皮2 小时前
Blue---二分算法(二分查找与二分答案)
算法
长河3 小时前
Java的GC(垃圾回收)中,标记无用对象的核心方法是可达性分析算法
java·jvm·算法
月光船幽幽3 小时前
加性偏移外推提升参数识别可靠性
python·算法
SHARK_pssm3 小时前
【C++——类和对象(下)】
开发语言·c++·经验分享·笔记
汉克老师4 小时前
GESP2026年9月认证C++二级( 第一部分选择题(1~7题)精讲
c++·gesp·小学生·学c++编程
Ivanqhz4 小时前
层归一化、残差、前馈网络与激活函数简述
服务器·数据库·人工智能·深度学习·算法