--- id: ff title: Flood Fill author: Darren Yao prerequisites: - dfs description: "A variant of DFS which finds connected components in a graph respresented by a grid." frequency: 3 --- import { Problem } from "../models"; export const problems = { sample: [ new Problem("LC", "Flood Fill", "https://leetcode.com/problems/flood-fill/", "Intro|Easy", false, []), new Problem("CSES", "Counting Rooms", "1192", "Easy", false, []), ], general: [ new Problem("CSES", "Labyrinth", "1193", "Easy", false, []), new Problem("Silver", "Count Cross", "716", "Easy", false, ["FF"]), new Problem("Silver", "Ice Perimeter", "895", "Easy", false, []), new Problem("Silver", "Switching on the Lights", "570", "Normal", false, []), new Problem("Silver", "Build Gates", "596", "Normal", false, []), new Problem("Silver", "Milk Pails", "620", "Normal", false, []), new Problem("Silver", "Where's Bessie?", "740", "Normal", false, []), new Problem("Silver", "Why Did the Cow Cross the Road III", "716", "Normal", false, []), new Problem("Silver", "Multiplayer Moo", "836", "Hard", false, []), new Problem("Silver", "Snow Boots", "811", "Hard", false, []), new Problem("Silver", "Mooyo Mooyo", "860", "Hard", false, []), ], };
module is based off this **Flood fill** is an algorithm that identifies and labels the connected component that a particular cell belongs to, in a multi-dimensional array. Essentially, it’s DFS, but on a grid, and we want to find the connected component of all the connected cells with the same number. For example, let’s look at the following grid and see how floodfill works, starting from the top-left cell. The color scheme will be the same: red for the node currently being processed, blue for nodes already visited, and uncolored for nodes not yet visited. (tables) As opposed to an explicit graph where the edges are given, a grid is an implicit graph. This means that the neighbors are just the nodes directly adjacent in the four cardinal directions. Usually, grids given in problems will be $N$ by $M$, so the first line of the input contains the numbers $N$ and $M$. In this example, we will use an two-dimensional integer array to store the grid, but depending on the problem, a two-dimensional character array or a two-dimensional boolean array may be more appropriate. Then, there are $N$ rows, each with $M$ numbers containing the contents of each square in the grid. Example input might look like the following (varies between problems): ``` 3 4 1 1 2 1 2 3 2 1 1 3 3 3 ``` And we’ll want to input the grid as follows: ```java static int[][] grid; static int n, m; public static void main(String[] args){ int n = r.nextInt(); int m = r.nextInt(); grid = new int[n][m]; for(int i = 0; i < n; i++){ for(int j = 0; j < m; j++){ grid[i][j] = r.nextInt(); } } } ``` ```cpp int grid[MAXN][MAXM]; int n, m; int main(){ cin >> n >> m; for(int i = 0; i < n; i++){ for(int j = 0; j < m; j++){ cin >> grid[i][j]; } } return 0; } ``` ## Implementation When doing floodfill, we will maintain an $N\times M$ array of booleans to keep track of which squares have been visited, and a global variable to maintain the size of the current component we are visiting. Make sure to store the grid, the visited array, dimensions, and the current size variable globally. This means that we want to recursively call the search function from the squares above, below, and to the left and right of our current square. The algorithm to find the size of a connected component in a grid using floodfill is as follows (we’ll also maintain a 2D visited array). ```cpp int grid[MAXN][MAXM]; // the grid itself int n, m; // grid dimensions, rows and columns bool visited[MAXN][MAXM]; // keeps track of which nodes have been visited int currentSize = 0; // reset to 0 each time we start a new component void floodfill(int r, int c, int color){ if(r < 0 || r >= n || c < 0 || c >= m) return; // if outside grid if(grid[r][c] != color) return; // wrong color if(visited[r][c]) return; // already visited this square visited[r][c] = true; // mark current square as visited currentSize++; // increment the size for each square we visit // recursively call floodfill for neighboring squares floodfill(r, c+1, color); floodfill(r, c-1, color); floodfill(r-1, c, color); floodfill(r+1, c, color); } int main(){ /** * input code and other problem-specific stuff here */ for(int i = 0; i < n; i++){ for(int j = 0; j < m; j++){ if(!visited[i][j]){ currentSize = 0; floodfill(i, j, grid[i][j]); // start a floodfill if the square hasn't // already been visited, and then // store or otherwise use the component size for whatever // it's needed for } } } return 0; } ``` ```java static int[][] grid; // the grid itself static int n, m; // grid dimensions, rows and columns static boolean[][] visited; // keeps track of which nodes have been visited static int currentSize = 0; // reset to 0 each time we start a new component public static void main(String[] args){ /** * input code and other problem-specific stuff here */ for(int i = 0; i < n; i++){ for(int j = 0; j < m; j++){ if(!visited[i][j]){ currentSize = 0; floodfill(i, j, grid[i][j]); // start a floodfill if the square hasn't already been visited, // and then store or otherwise use the component size // for whatever it's needed for } } } } static void floodfill(int r, int c, int color){ if(r < 0 || r >= n || c < 0 || c >= m) return; // if outside grid if(grid[r][c] != color) return; // wrong color if(visited[r][c]) return; // already visited this square visited[r][c] = true; // mark current square as visited currentSize++; // increment the size for each square we visit // recursively call floodfill for neighboring squares floodfill(r, c+1, color); floodfill(r, c-1, color); floodfill(r-1, c, color); floodfill(r+1, c, color); } ``` ## Problems