classSolution: defmaximumSafenessFactor(self, grid: List[List[int]]) -> int: n = len(grid) q = [] dis = [[-1] * n for _ inrange(n)] for i, row inenumerate(grid): for j, x inenumerate(row): if x: q.append((i, j)) dis[i][j] = 0
groups = [q] while q: # 多源 BFS tmp = q q = [] for i, j in tmp: for x, y in (i + 1, j), (i - 1, j), (i, j + 1), (i, j - 1): if0 <= x < n and0 <= y < n and dis[x][y] < 0: q.append((x, y)) dis[x][y] = len(groups) groups.append(q) # 相同 dis 分组记录
# 并查集模板 fa = list(range(n * n)) deffind(x: int) -> int: if fa[x] != x: fa[x] = find(fa[x]) return fa[x]
for d inrange(len(groups) - 2, 0, -1): for i, j in groups[d]: for x, y in (i + 1, j), (i - 1, j), (i, j + 1), (i, j - 1): if0 <= x < n and0 <= y < n and dis[x][y] >= dis[i][j]: fa[find(x * n + y)] = find(i * n + j) if find(0) == find(n * n - 1): # 写这里判断更快些 return d return0
publicintmaximumSafenessFactor(List<List<Integer>> grid) { intn= grid.size(); varq=newArrayList<int[]>(); vardis=newint[n][n]; for (inti=0; i < n; i++) { for (intj=0; j < n; j++) { if (grid.get(i).get(j) > 0) { q.add(newint[]{i, j}); } else { dis[i][j] = -1; } } }
vargroups=newArrayList<List<int[]>>(); groups.add(q); while (!q.isEmpty()) { // 多源 BFS vartmp= q; q = newArrayList<>(); for (var p : tmp) { for (var d : DIRS) { intx= p[0] + d[0], y = p[1] + d[1]; if (0 <= x && x < n && 0 <= y && y < n && dis[x][y] < 0) { q.add(newint[]{x, y}); dis[x][y] = groups.size(); } } } groups.add(q); // 相同 dis 分组记录 }
// 并查集 fa = newint[n * n]; for (inti=0; i < n * n; i++) fa[i] = i;
for (intans= groups.size() - 2; ans > 0; ans--) { varg= groups.get(ans); for (var p : groups.get(ans)) { inti= p[0], j = p[1]; for (var d : DIRS) { intx= i + d[0], y = j + d[1]; if (0 <= x && x < n && 0 <= y && y < n && dis[x][y] >= dis[i][j]) fa[find(x * n + y)] = find(i * n + j); } } if (find(0) == find(n * n - 1)) // 写这里判断更快些 return ans; } return0; }
classSolution { staticconstexprint dirs[4][2] = { {-1, 0}, {1, 0}, {0, -1}, {0, 1} }; public: intmaximumSafenessFactor(vector<vector<int>> &grid){ int n = grid.size(); vector<pair<int, int>> q; vector<vector<int>> dis(n, vector<int>(n, -1)); for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { if (grid[i][j]) { q.emplace_back(i, j); dis[i][j] = 0; } } }
vector<vector<pair<int, int>>> groups = {q}; while (!q.empty()) { // 多源 BFS vector<pair<int, int>> nq; for (auto &[i, j]: q) { for (auto &d: dirs) { int x = i + d[0], y = j + d[1]; if (0 <= x && x < n && 0 <= y && y < n && dis[x][y] < 0) { nq.emplace_back(x, y); dis[x][y] = groups.size(); } } } groups.push_back(nq); // 相同 dis 分组记录 q = move(nq); }
// 并查集模板 vector<int> fa(n * n); iota(fa.begin(), fa.end(), 0); function<int(int)> find = [&](int x) -> int { return fa[x] == x ? x : fa[x] = find(fa[x]); };
for (int ans = (int) groups.size() - 2; ans > 0; ans--) { for (auto &[i, j]: groups[ans]) { for (auto &d: dirs) { int x = i + d[0], y = j + d[1]; if (0 <= x && x < n && 0 <= y && y < n && dis[x][y] >= dis[i][j]) fa[find(x * n + y)] = find(i * n + j); } } if (find(0) == find(n * n - 1)) // 写这里判断更快些 return ans; } return0; } };
funcmaximumSafenessFactor(grid [][]int)int { n := len(grid) type pair struct{ x, y int } q := []pair{} dis := make([][]int, n) for i, row := range grid { dis[i] = make([]int, n) for j, x := range row { if x > 0 { q = append(q, pair{i, j}) } else { dis[i][j] = -1 } } }
dir4 := []pair{ {-1, 0}, {1, 0}, {0, -1}, {0, 1} } groups := [][]pair{q} forlen(q) > 0 { // 多源 BFS tmp := q q = nil for _, p := range tmp { for _, d := range dir4 { x, y := p.x+d.x, p.y+d.y if0 <= x && x < n && 0 <= y && y < n && dis[x][y] < 0 { q = append(q, pair{x, y}) dis[x][y] = len(groups) } } } groups = append(groups, q) // 相同 dis 分组记录 }
// 并查集模板 fa := make([]int, n*n) for i := range fa { fa[i] = i } var find func(int)int find = func(x int)int { if fa[x] != x { fa[x] = find(fa[x]) } return fa[x] }
for ans := len(groups) - 2; ans > 0; ans-- { for _, p := range groups[ans] { i, j := p.x, p.y for _, d := range dir4 { x, y := p.x+d.x, p.y+d.y if0 <= x && x < n && 0 <= y && y < n && dis[x][y] >= dis[i][j] { fa[find(x*n+y)] = find(i*n + j) } } } if find(0) == find(n*n-1) { // 写这里判断更快些 return ans } } return0 }
复杂度分析
时间复杂度:\mathcal{O}(n^2\log n) 或者 \mathcal{O}(n^2),其中 n 为 grid 的长度。时间复杂度取决于并查集的实现,加上按秩合并的话,均摊地说并查集的操作可以视作是 O(1) 的。