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;
    }
};
相关推荐
码客-ygluu5 小时前
一个通用游戏数据服务器
c++·架构
another heaven6 小时前
【C/C++ Ranges 是零开销抽象吗?拆开管道、惰性求值和编译期膨胀】
c语言·开发语言·c++
Code_Solitude6 小时前
C语言动态内存 + 柔性数组 + 数组名退化
c语言·算法·柔性数组
上海潭龙东海科技有限公司6 小时前
客运站管控之动态孪生技术方案(新增一屏管控模块
数据仓库·人工智能·算法·重构·动态规划
YLCHUP8 小时前
【思维&图论建模】题解:债权(debt)_图论_建模_思路转化_思维题目_C++算法竞赛
c++·笔记·算法·数学建模·贪心算法·深度优先·图论
xiaoye-duck8 小时前
《C++ 项目:手写大模型接入 SDK》会话模块整合:内存 SessionManager 与 DataManager 持久化联动
开发语言·数据库·c++·语言模型
思麟呀9 小时前
背包DP(01背包+完全背包)
c++·算法
笑容掩饰我的失落10 小时前
区块链从小白到精通(七):Solidity 语法精讲——数据类型、函数、修饰器与事件
算法·区块链·php·智能合约·哈希算法
旖旎夜光10 小时前
【C++ 基础入门】C++11 新特性(中):右值引用、移动语义与完美转发
开发语言·c++·笔记·学习