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;
    }
};
相关推荐
ysa0510302 小时前
【板子】短序列dp(换成维护更小常数维度的dp)
c++·笔记·算法·板子
shwill1232 小时前
PID 算法(三)--- 增量 PID ↔ 单神经元 PID 等价映射
linux·算法
wabs6663 小时前
关于图论【卡码网110.字符串迁移的思考】
数据结构·算法·图论
hanlin033 小时前
刷题笔记:力扣第242、349题(哈希表)
笔记·算法·leetcode
aramae4 小时前
C++ IO流完全指南:从C标准库到C++流式编程
服务器·c语言·开发语言·c++·后端
_wyt0014 小时前
c++里的族谱:树
c++·
only-qi5 小时前
大模型Agent面试攻略:落地工程痛点、评估体系与Agentic RAG核心精讲
人工智能·算法·面试·职场和发展·langchain·rag
@三十一Y5 小时前
C++:AVL树实现
c++
haolin123.6 小时前
类和对象(上)
开发语言·c++