最短路径中超级源点的使用
1. 问题:
在最短路径问题中,如果源点有多个,我之前的做法可能都是遍历这n个源点
2. 背景题目
leetcode题目:大致意思如下
给定一个 01 矩阵 mat,输出一个大小相同的矩阵,其中每一个格子是 mat 中对应位置元素到最近的 0 的距离。
(斜对角的距离是2)
(简单理解就是地图上陆地每个位置到海洋的最短距离)
2.1之前的思考
遍历这个二维矩阵呗,对每个1进行一次BFS,求最短路径
但后来发现,假设有个A位置,则这个A可能不止一次的要被BFS访问到,因为他可能出现在很多结点的BFS路径上(比如这个A是海边的一个结点)
2.2 问题的简化
如果海洋只有一个点的话,问题就可以倒过来想了,海洋到所有陆地的最短距离(单个源点)
2.3 超级源点(超级0)
而当海洋面积变大的时候(多个源点),可以考虑设置一个超级源点super0,他到所有海洋(0)的距离都是1,
这时候,这些0其实就相当于从超级源点开始BFS后的第一步
这时候,每一个陆地(1)就只用被bFS跑一次了
并且,更重要的是,避免了多次使用BFS时遍历标记位的复杂考虑,总不能每个顶点都重置一次标记矩阵吧。。
2.4 具体实施
所有的0都相当于超级0进行BFS时的第一层,就直接double fori把所有0都压到队列里就ok了,然后一切照旧
题目解答
public int[][] updateMatrix(int[][] mat) {
if(mat==null)return null;
int[][] dist=new int[][]{{0,1},{1,0},{0,-1},{-1,0}};//方向指示器,用于帮助找到下一个压入队列的坐标
//也可以写四个坐标然后挨个add,但是太麻烦,这样就可以for循环了
int row=mat.length;
int col=mat[0].length;
int[][] result=new int[row][col];
int[][] seen=new int[row][col];//当然也可以考虑把原矩阵遍历过得位置赋值为-1
Queue<int[]> queue=new LinkedList<>();
for (int i = 0; i <row; i++) {
for (int j = 0; j < col; j++) {
if(mat[i][j]==0){//开始广度优先找边界
queue.add(new int[]{i,j});
seen[i][j]=1;
}
}
}
while(!queue.isEmpty()){
int[] point=queue.poll();
int i=point[0],j=point[1];//队列中取出的点的横纵坐标
//visit()位置1//放在这里就需要再做一次四个方向上的遍历找到上一步的位置
for(int d=0;d<4;d++){//就不用每个方向都做一次判断了,学会!
int i_=i+dist[d][0],j_=j+dist[d][1];
if(i_>=0&&i_<row&&j_>=0&&j_<col&&seen[i_][j_]==0){
//visit()位置2,
//放在这里的好处就是就获得当前位置和上(下)一步位置之间的关系
seen[i_][j_]=1;//遍历过了
result[i_][j_]=result[i][j]+1;
queue.add(new int[]{i_,j_});
}
}
}
return result;
}
本文来自博客园,作者:荧惑微光,转载请注明原文链接:https://www.cnblogs.com/yinghuoweiguang/p/15799531.html