934. Shortest Bridge
题解
题目是求两个连通块的最短路径,可以用宽搜。
宽搜有几个要注意的地方,1. 如何区分不同的连通块,2. 不要重复搜索。
在遍历的时候,首先找到第一个连通块,使用flood fill算法,把对应的连通块染色。然后再flood fill的同时,找到边缘的所有点,加入队列,之后在队列中,进行宽搜找到最短距离。
另外宽搜的时候,可以用距离数组维护是否需要加入队列中,不需要hash表。
代码
由于是宽搜,距离数组更新的时候必然是第一次遍历的时候,因此不会重复遍历。
class Solution {public:int n, m;int dx[4] = {0, 1, 0, -1};int dy[4] = {1, 0, -1, 0};typedef pair<int, int> PII;vector<vector<int>> dist;queue<PII> q;void flood_fill(vector<vector<int>>& grid, int x, int y) {grid[x][y] = -1;dist[x][y] = 0;q.push({x, y});for (int i = 0; i < 4; i ++) {int a = x + dx[i];int b = y + dy[i];if (a >= 0 && a < n && b >= 0 && b < m && grid[a][b] == 1) {flood_fill(grid, a, b);}}}int get_shortest_bridge(vector<vector<int>>& grid, int x, int y) {flood_fill(grid, x, y);while(q.size()) {int k = q.size();for (int i = 0; i < k; i ++) {auto p = q.front();q.pop();int x = p.first, y = p.second;// cout << x <<", " << y <<endl;for (int j = 0; j < 4; j ++) {int a = x + dx[j];int b = y + dy[j];// cout << "(" << a << ", " << b << ")" << endl;if (a >= 0 && a < n && b >= 0 && b < m && dist[a][b] > dist[x][y] + 1) {dist[a][b] = dist[x][y] + 1;q.push({a, b});}if (a >= 0 && a < n && b >= 0 && b < m && grid[a][b] == 1) {return dist[a][b] - 1;}}}}return -1;}int shortestBridge(vector<vector<int>>& grid) {n = grid.size(), m = grid[0].size();dist = vector<vector<int>>(n, vector<int>(m, 1e8));for(int i = 0; i < n; i ++) {for (int j = 0; j < m; j ++) {if (grid[i][j] == 1) {return get_shortest_bridge(grid, i, j);}}}return -1;}};
