多源BFS解决最短路问题

目录

01矩阵

飞地的数量

地图中的最高点

地图分析


01矩阵

题目

思路

解决这道题使用的方法是多源BFS,多源BFS区别于单源BFS的地方在于起点不是一个多个,首先将矩阵中所有的0加入队列中,创建一个和原始矩阵大小相同的矩阵dists,矩阵dists中的值为每个点距离0的最短距离,然后进行宽度优先遍历,将没有遍历过的点添加到队列中,并更新该点到0的最短距离,最后返回dists矩阵就可以了。

代码

class Solution {
public:
    vector<vector<int>> updateMatrix(vector<vector<int>>& mat) {
        int m=mat.size(),n=mat[0].size();
        vector<vector<int>> dists(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){
                    q.push({i,j});
                    dists[i][j]=0;
                }
            }
        int dx[4]={1,-1,0,0};
        int dy[4]={0,0,1,-1};
        while(!q.empty()){
            int sz=q.size();
            while(sz--){
                auto [a,b]=q.front();
                q.pop();
                for(int k=0;k<4;k++){
                    int x=a+dx[k],y=b+dy[k];
                    if(x>=0 && x<m && y>=0 && y<n && dists[x][y]==-1){
                        q.push({x,y});
                        dists[x][y]=dists[a][b]+1;
                    }
                }
            }
        }
        return dists;
    }
};
飞地的数量

题目

思路

解决这道题使用的方法是多源BFS,多源BFS区别于单源BFS的地方在于起点不是一个多个。

我们可能想到遍历二维矩阵中的每一个点,对该点进行DFS或者BFS,但是这样的话有点麻烦,我们不妨采用“正难则反”的思想,将二维矩阵中四周值为1的点加入队列中,然后进行宽度优先遍历,将没有访问过的且值为1的点加入队列中。

最后,遍历二维矩阵中所有的点,如果该位置值为1且没有被访问过,那么这个位置就是一个飞地,统计所有的飞地的数量,返回即可。

代码

class Solution {
public:
    int numEnclaves(vector<vector<int>>& grid) {
        int m=grid.size(),n=grid[0].size();
        vector<vector<bool>> vis(m,vector<bool>(n));
        queue<pair<int,int>> q;
        for(int i=0;i<m;i++){
            if(grid[i][0]==1) q.push({i,0}),vis[i][0]=true;
            if(grid[i][n-1]==1) q.push({i,n-1}),vis[i][n-1]=true;;
        }
        for(int i=0;i<n;i++){
            if(grid[0][i]==1) q.push({0,i}),vis[0][i]=true;;
            if(grid[m-1][i]==1) q.push({m-1,i}),vis[m-1][i]=true;;
        }
        int dx[4]={1,-1,0,0};
        int dy[4]={0,0,1,-1};
        while(!q.empty()){
            int sz=q.size();
            while(sz--){
                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] && !vis[x][y])
                        q.push({x,y}),vis[x][y]=true;
                }
            }
        }
        int ret=0;
        for(int i=0;i<m;i++)
            for(int j=0;j<n;j++)
                if(grid[i][j]==1 && vis[i][j]==false)
                    ret++;
        return ret;
    }
};
地图中的最高点

题目

思路

解决这道题使用的方法是多源BFS,多源BFS区别于单源BFS的地方在于起点不是一个多个。

首先,我们创建一个和原始矩阵大小相同的二维矩阵heights,然后扫描整个二维矩阵,将所有值为1的点加入队列中,然后进行BFS,将没有访问过的点加入队列中,并更新该位置的高度值,最后,返回二维矩阵heighgts就可以了。

代码

class Solution {
public:
    vector<vector<int>> highestPeak(vector<vector<int>>& isWater) {
        int m=isWater.size(),n=isWater[0].size();
        vector<vector<int>> heights(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]==1)
                    q.push({i,j}),heights[i][j]=0;
        int dx[4]={1,-1,0,0};
        int dy[4]={0,0,1,-1};
        while(!q.empty()){
            int sz=q.size();
            while(sz--){
                auto [a,b]=q.front();
                q.pop();
                for(int k=0;k<4;k++){
                    int x=a+dx[k],y=b+dy[k];
                    if(x>=0 && x<m && y>=0 && y<n && isWater[x][y]==0 && heights[x][y]==-1)
                        q.push({x,y}),heights[x][y]=heights[a][b]+1;
                }
            }
        }
        return heights;
    }
};
地图分析

题目

思路

解决这道题使用的方法是多源BFS,多源BFS区别于单源BFS的地方在于起点不是一个多个。

我们可能会想到对矩阵中所有值为0的点进行BFS,找出所有距离陆地的距离中的最大距离,但是这样有点麻烦,我们不妨对矩阵中所有值为1的点进行BFS,如果队列的大小为n*n或者为0,说明只存在陆地或者只存在海洋,返回-1即可;否则,创建一个和原始矩阵大小相同的二维矩阵dists,然后将没有访问过的点添加到队列中,并更新该位置到陆地的距离,最后返回dists矩阵中的最大值即可。

代码

class Solution {
public:
    int maxDistance(vector<vector<int>>& grid) {
        int n=grid.size();
        vector<vector<int>> dists(n,vector<int>(n,-1));
        queue<pair<int,int>> q;
        for(int i=0;i<n;i++)
            for(int j=0;j<n;j++)
                if(grid[i][j]==1)
                    q.push({i,j}),dists[i][j]=0;
        if(q.size()==n*n || q.size()==0)
            return -1;
        int dx[4]={1,-1,0,0};
        int dy[4]={0,0,1,-1};
        while(!q.empty()){
            int sz=q.size();
            while(sz--){
                auto [a,b]=q.front();
                q.pop();
                for(int k=0;k<4;k++){
                    int x=a+dx[k],y=b+dy[k];
                    if(x>=0 && x<n && y>=0 && y<n && dists[x][y]==-1)
                        q.push({x,y}),dists[x][y]=dists[a][b]+1;
                }
            }
        }
        int ret=0;
        for(int i=0;i<n;i++)
            for(int j=0;j<n;j++)
                ret=max(ret,dists[i][j]);
        return ret;
    }
};

  • 32
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 40
    评论
评论 40
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

新绿MEHO

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值