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;
    }
};
相关推荐
mCell2 小时前
Lua 编程入门:从基础语法到元表
javascript·算法·lua
wuyk5554 小时前
98.C语言易混难点:字符数组与字符串指针的底层差异
c语言·开发语言·c++·stm32·嵌入式硬件·算法
峥无4 小时前
从0到1手撕红黑树:封装实现 my_map 与 my_set(SGI-STL 源码级深度解析)
开发语言·c++·笔记·算法·stl
波特率1152004 小时前
C++新特性---属性说明符与标准属性
开发语言·c++
不会代码的小猴5 小时前
3. 控件学习1
开发语言·c++·笔记·qt·算法
203号居民6 小时前
LeetCode hot 100 —41. 缺失的第一个正数
数据结构·算法·leetcode
专注仿真9 小时前
问答大模型技术方案算法实现-熵权法融合算法 + 交叉编码器重排算法
人工智能·python·算法·语言模型·问答大模型关键算法·熵权融合算法·交叉编码器重排算法
烧酒同学9 小时前
【C++】记录size of std::vector的巧妙坑
开发语言·c++·图形渲染
地平线开发者10 小时前
量化为什么会有损失:从量化误差到精度下降
算法