DSA sheet / Graph

Counting Rooms

easy about 20 min BFS / DFSgridflood-fillconnected-components
Open on CSES

The problem in brief

You get an n by m map (both up to 1000) where each cell is a floor or a wall. A room is a maximal set of floor cells connected through horizontal and vertical steps. Print how many rooms there are.

Try it

Tab indents; press Esc, then Tab, to leave the box. Ctrl+Enter runs.

Hints

Stuck? Reveal one hint at a time. Each nudges without giving away the next.

The walkthrough

Spoilers ahead: open a section only after you have given the hints a fair try.

How to think

“Count the separate blobs” is a connected-components problem, and the standard tool is flood fill: scan the cells; the first time you meet an unvisited floor cell you have found a new room, so add one to the count and then explore the whole room, marking every cell so you never count it again. Each cell is marked once, so the total work is proportional to the number of cells.

The practical risk is depth. A recursive DFS on a snake-shaped room of a million cells recurses a million frames deep, which overflows the stack in most languages. Use an explicit stack or a queue (BFS) instead; both give the same components. The habit: for graph traversals on large inputs, write them iteratively.

Intuition

Pour paint on one floor cell: it spreads to every neighbouring floor cell, and so on until the whole room is painted. Walk the map and each time you find a floor cell that is not painted yet, that is a new room: pour paint again and count.

Approach
  1. Read the grid; mark walls as visited (or keep a separate visited array).
  2. For each cell in reading order: if it is an unvisited floor, increment the answer and run a flood fill from it (iterative stack/queue over the four neighbours, marking cells as you push).
  3. Print the count.

Pitfalls: mark a cell when you push it, not when you pop it, so it is never pushed twice; check bounds before indexing; use iteration, not recursion; read rows as strings.

Complexity

O(n * m) time and memory.

Solutions

Written from scratch and checked by compiling and running each one against a brute force on random inputs. Fast input/output, the way you would submit it.

Show solutions (C++17, Python 3, Java 17, Node.js)
#include <bits/stdc++.h>
using namespace std;

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int n, m;
    cin >> n >> m;
    vector<string> g(n);
    for (auto &row : g) cin >> row;
    int rooms = 0;
    const int dr[4] = {1, -1, 0, 0}, dc[4] = {0, 0, 1, -1};
    vector<pair<int, int>> stack;
    for (int r = 0; r < n; r++) {
        for (int c = 0; c < m; c++) {
            if (g[r][c] != '.') continue;
            rooms++;
            g[r][c] = '#';
            stack.push_back({r, c});
            while (!stack.empty()) {
                auto [cr, cc] = stack.back();
                stack.pop_back();
                for (int k = 0; k < 4; k++) {
                    int nr = cr + dr[k], nc = cc + dc[k];
                    if (nr >= 0 && nr < n && nc >= 0 && nc < m && g[nr][nc] == '.') {
                        g[nr][nc] = '#';
                        stack.push_back({nr, nc});
                    }
                }
            }
        }
    }
    cout << rooms << "\n";
    return 0;
}

Problem: CSES Problem Set (Antti Laaksonen, University of Helsinki), CC BY-NC-SA 4.0. The explanations and code above are original (© Anupam Kumar).

Related problems

Back to the sheet