題目連結:1568. Minimum Number of Days to Disconnect Island
題目敘述#
You are given an m x n
binary grid grid
where 1
represents land and 0
represents water. An island is a maximal 4-directionally (horizontal or vertical) connected group of 1
’s.
The grid is said to be connected if we have exactly one island, otherwise is said disconnected.
In one day, we are allowed to change any single land cell (1)
into a water cell (0)
.
Return the minimum number of days to disconnect the grid.
解題思路#
程式碼#
C++#
class Solution {
public:
int m, n;
int ones; // number of one in grid
int component; // number of component
int ap_cnt; // number of articulation points
int dfn_cnt;
vector<vector<int>> dfn, low;
int dir[4][2] = {0, 1, 1, 0, 0, -1, -1, 0};
// Tarjan's Algorithm
void dfs(int y, int x, int py, int px, vector<vector<int>>& grid) {
int child = 0;
bool is_ap = false;
// 把走過的節點標號,low 預設為自己的編號
dfn[y][x] = low[y][x] = ++dfn_cnt;
ones++;
for (int i = 0; i < 4; i++) {
int ny = y + dir[i][0];
int nx = x + dir[i][1];
if (ny < 0 || ny >= m || nx < 0 || nx >= n || grid[ny][nx] == 0)
continue;
if (!dfn[ny][nx]) { // 還沒走過的點
child++;
dfs(ny, nx, y, x, grid);
low[y][x] = min(low[y][x], low[ny][nx]);
if (low[ny][nx] >= dfn[y][x]) {
// 節點 (ny,nx) 回不到比 (y,x) 更早的祖先,因此 (y,x) 是關節點
is_ap = true;
}
} else if (ny != py || nx != px) {
// 已走過的點,且該點不等於父節點
low[y][x] = min(low[y][x], dfn[ny][nx]); // 嘗試能不能回到更上層的祖先
}
}
if (y == py && x == px && child > 1) {
// 節點為 DFS tree 的 root,且有兩個以上的子樹
ap_cnt++;
} else if ((y !=py || x != px) && is_ap) {
// 節點不是 DFS tree 的 root
ap_cnt++;
}
}
int minDays(vector<vector<int>>& grid) {
m = grid.size();
n = grid[0].size();
dfn.resize(m, vector<int>(n));
low.resize(m, vector<int>(n));
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (grid[i][j] == 1 && !dfn[i][j]) {
dfs(i, j, i, j, grid);
component++;
}
}
}
if (component > 1) {
return 0;
} else if (ones <= 2) {
return ones;
} else {
return ap_cnt ? 1 : 2;
}
}
};