【BFS专题】— 多源最短路问题

1、矩阵 - 力扣(LeetCode)

思路:

  1. 首先创建一个dist数组,将dist数组初始化为-1,表示该位置没有被搜索和记录该位置的值
  2. 然后再遍历mat数组,将数组中的 0 添加到队列中,并且修改dist对应位置的值为0
  3. 然后就依次往外拓展,每次新拓展的点的值就是dist位置的值加一
  4. 代码:
    class Solution {
        int[] dx = {0, 0, -1, 1};
        int[] dy = {1, -1, 0, 0};
        public int[][] updateMatrix(int[][] mat) {
            //1、创建一个dist数组,并且初始化为-1
            int[][] dist = new int[mat.length][mat[0].length];
            for(int i = 0; i < mat.length; i++){
                for(int j = 0; j < mat[0].length; j++){
                dist[i][j] = -1;
                }
            }
    
            //2、遍历mat数组,将0位置加入队列中,并且修改dist对应位置的值为0
            Queue<int[]> q = new LinkedList<>();
            for(int i = 0; i < mat.length; i++){
                for(int j = 0; j < mat[0].length; j++){
                    if(mat[i][j] == 0){
                        q.offer(new int[]{i, j});
                        dist[i][j] = 0;
                    }
                }
            }
    
            //3、向外一层一层的拓展
            while(!q.isEmpty()){
                int[] t = q.poll();
                int a = t[0];
                int b = t[1];
                for(int i = 0; i < 4; i++){
                    int x = a + dx[i];
                    int y = b + dy[i];
                    if(x >= 0 && x < mat.length && y >= 0 && y < mat[0].length && dist[x][y] == -1){
                        q.offer(new int[]{x, y});
                        dist[x][y] = dist[a][b] + 1;
                    }
                }
            }
            return dist;
        }
    }

 2、飞地的数量 - 力扣(LeetCode)

 

思路:

  1. 要求被0包围的1 的数量,我们可以反过来,先求出边界上的1和其相联的1,标记一下
  2. 然后再遍历数组,剩下没有被标记的1就是我们要求的1,统计其数量
  3. 代码:
    class Solution {
        int[] dx = {0, 0, -1, 1};
        int[] dy = {1, -1, 0, 0};
        public int numEnclaves(int[][] grid) {
            int m = grid.length;
            int n = grid[0].length;
            boolean[][] vis = new boolean[m][n];
            Queue<int[]> q = new LinkedList<>();
            //1、将边界的1加入到队列中
            for(int i = 0; i < m; i++){
                if(grid[i][0] == 1){
                    q.offer(new int[]{i, 0});
                    vis[i][0] = true;
                }
                if(grid[i][n-1] == 1){
                    q.offer(new int[]{i, n - 1});
                    vis[i][n-1] = true;
                }
            }
            for(int i = 0; i < n; i++){
                if(grid[0][i] == 1){
                    q.offer(new int[]{0, i});
                    vis[0][i] = true;
                }
                if(grid[m-1][i] == 1){
                    q.offer(new int[]{m-1, i});
                    vis[m-1][i] = true;
                }
            }
    
            //2、遍历队列,向外拓展
            while(!q.isEmpty()){
                int[] t = q.poll();
                int a = t[0];
                int b = t[1];
                for(int i = 0; i < 4; i++){
                    int x = a + dx[i];
                    int y = b + dy[i];
                    if(x >= 0 && y >= 0 && x < m & y < n && grid[x][y] == 1 && !vis[x][y]){
                        q.offer(new int[]{x, y});
                        vis[x][y] = true;
                    }
                }
            }
    
            //3、提取结果
            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]){
                        ret++;
                    }
                }
            }
            return ret;
        }
    }

 3、地图中的最高点 - 力扣(LeetCode)

思路:

  1. 首先创建一个dist数组,初始化为-1,表示没有搜索过的
  2. 让遍历isWater数组,将值为1 的位置添加到队列中,并且修改dist对应位置的值为0
  3. 最后进行多源bfs遍历
  4. 代码:
    class Solution {
        int[] dx = {0, 0, -1, 1};
        int[] dy = {1, -1, 0, 0};
        public int[][] highestPeak(int[][] isWater) {
            int m = isWater.length;
            int n = isWater[0].length;
            int[][] dist = new int[m][n];
            Queue<int[]> q = new LinkedList<>();
    
            //1、将所有源点加入到队列
            for(int i = 0; i < m; i++){
                for(int j = 0; j < n; j++){
                    //初始化dist数组
                    dist[i][j] = -1;
                    if(isWater[i][j] == 1){
                        dist[i][j] = 0;
                        q.offer(new int[]{i, j});
                    }
                }
            }
    
            //2、多源bfs
            while(!q.isEmpty()){
                int[] t = q.poll();
                int a = t[0];
                int b = t[1];
                for(int i = 0; i < 4; i++){
                    int x = a + dx[i];
                    int y = b + dy[i];
                    if(x >= 0 && y >= 0 && x < m && y < n && dist[x][y] == -1){
                        //当前位置的值就是原来拓展位置的值 + 1
                        dist[x][y] = dist[a][b] + 1;
                        q.offer(new int[]{x, y});
                    }
                }
            }
            return dist;
        }
    }

 4、地图分析 - 力扣(LeetCode)

思路:

  1. 我们可以从陆地开始,遍历距离,
  2. 代码:
    class Solution {
        int[] dx = {0, 0, -1, 1};
        int[] dy = {1, -1, 0, 0};
        public int maxDistance(int[][] grid) {
            int m = grid.length;
            int n = grid[0].length;
            int[][] dist = new int[m][n];
            Queue<int[]> q = new LinkedList<>();
            //1、将多个源点入队
            for(int i = 0; i < m; i++){
                for(int j = 0; j < n; j++){
                    dist[i][j] = -1;
                    if(grid[i][j] == 1){
                        dist[i][j] = 0;
                        q.offer(new int[]{i, j});
                    }
                }
            }
    
            //2、多源bfs
            int ret = -1;
            while(!q.isEmpty()){
                int[] t = q.poll();
                int a = t[0];
                int b = t[1];
                for(int i = 0; i < 4; i++){
                    int x = a + dx[i];
                    int y = b + dy[i];
                    if(x >= 0 && y >= 0 && x < m && y < n && dist[x][y] == -1){
                        dist[x][y] = dist[a][b] + 1;
                        q.offer(new int[]{x, y});
                        ret = Math.max(ret, dist[x][y]);
                    }
                }
            }
            return ret;
        }
    }
以下是使用Java语言实现多源最短路算法的示例代码: ``` import java.util.*; public class MultiSourceShortestPath { static class Edge { int source, dest, weight; public Edge(int source, int dest, int weight) { this.source = source; this.dest = dest; this.weight = weight; } } static int V, E; static List<Edge>[] graph; public static void main(String[] args) { Scanner sc = new Scanner(System.in); V = sc.nextInt(); E = sc.nextInt(); graph = new ArrayList[V]; for (int i = 0; i < V; i++) { graph[i] = new ArrayList<>(); } for (int i = 0; i < E; i++) { int u = sc.nextInt(); int v = sc.nextInt(); int w = sc.nextInt(); graph[u].add(new Edge(u, v, w)); graph[v].add(new Edge(v, u, w)); } int[] dist = multiSourceShortestPath(); for (int i = 0; i < V; i++) { System.out.print(dist[i] + " "); } } static int[] multiSourceShortestPath() { int[] dist = new int[V]; Arrays.fill(dist, Integer.MAX_VALUE); Queue<Integer> q = new LinkedList<>(); for (int i = 0; i < V; i++) { q.add(i); dist[i] = 0; } while (!q.isEmpty()) { int u = q.poll(); for (Edge e : graph[u]) { int v = e.dest; int w = e.weight; if (dist[v] > dist[u] + w) { dist[v] = dist[u] + w; q.add(v); } } } return dist; } } ``` 该算法使用广度优先搜索(BFS)实现。首先将所有顶点添加到队列中,并将它们的距离初始化为0。然后,对于队列中的每个顶点,遍历它的所有邻居,并更新它们到源点的距离。如果距离被更新,则将邻居添加到队列中以进一步处理。 该算法的时间复杂度为O(V+E),其中V是顶点数,E是边数。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值