Counting Closed Regions in a Path Using Euler's Formula

The Problem

Imagine you’re given a sequence of directions (N, S, E, W) that describe a path on a 2D grid starting from the origin (0, 0). As you follow this path, you might cross your own trail, creating closed regions or “loops” in the plane.

Question: How many closed regions does your path create?

This seemingly simple question leads us to a beautiful application of graph theory and one of the most elegant formulas in discrete mathematics: Euler’s Formula for Planar Graphs.

A Concrete Example

Let’s trace through the path: NNNESWWWSSEEEE

Starting from (0,0), we move:

  • NNN: up 3 steps → (0,3)
  • E: right → (1,3)
  • S: down → (1,2)
  • WWW: left 3 steps → (-2,2)
  • SS: down 2 steps → (-2,0)
  • EEEE: right 4 steps → (2,0)
graph LR
    A["(0,0)"] --> B["(0,1)"]
    B --> C["(0,2)"]
    C --> D["(0,3)"]
    D --> E["(1,3)"]
    E --> F["(1,2)"]
    F --> G["(0,2)"]
    G --> H["(-1,2)"]
    H --> I["(-2,2)"]
    I --> J["(-2,1)"]
    J --> K["(-2,0)"]
    K --> L["(-1,0)"]
    L --> M["(0,0)"]
    M --> N["(1,0)"]
    N --> O["(2,0)"]

If we visualize this path carefully, we can see it creates 2 closed regions!

The Naive Approach: Cycle Detection

My first instinct was to model this as a graph problem:

  1. Create a node for each unique coordinate visited
  2. Add edges between consecutive points in the path
  3. Run DFS to detect cycles

Here’s what that looks like:

void dfsVisit(int u, const vector<vector<int>>& graph, 
              vector<int>& color, vector<int>& parent, 
              int& cycleCount) {
    color[u] = 1; // Gray - visiting
    
    for (int v : graph[u]) {
        if (color[v] == 0) { // Unvisited
            parent[v] = u;
            dfsVisit(v, graph, color, parent, cycleCount);
        } 
        else if (color[v] == 1 && parent[u] != v) {
            // Back edge found!
            cycleCount++;
        }
    }
    
    color[u] = 2; // Black - done
}

Problem: This approach is tricky! How do you avoid double-counting? How do you handle overlapping cycles? The relationship between back edges and actual closed regions isn’t straightforward.

The Elegant Solution: Euler’s Formula

Then comes the insight: the graph we’re building is planar (can be drawn on a plane without edge crossings). For such graphs, there’s a beautiful relationship:

[ V - E + F = 2 ]

Where:

  • $V$ = number of vertices (unique points)
  • $E$ = number of edges (unique connections)
  • $F$ = number of faces (including the outer infinite face)

Since we want only the bounded faces (closed regions), we subtract 1:

\[\text{Closed Regions} = F - 1 = E - V + 1\]

That’s it! Count vertices, count edges, apply the formula.

The Implementation

#include <bits/stdc++.h>
using namespace std;

typedef pair<int, int> pii;

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    
    int N;
    cin >> N;
    string path;
    cin >> path;
    
    map<pii, int> points_index;
    points_index[{0, 0}] = 0;
    pii current = {0, 0};
    
    // Track unique edges
    set<pair<int,int>> edges;
    
    for (char step : path) {
        int i = points_index[current];
        
        // Move based on direction
        if (step == 'N') current.second++;
        else if (step == 'S') current.second--;
        else if (step == 'E') current.first++;
        else if (step == 'W') current.first--;
        
        // Add new point if needed
        if (!points_index.count(current)) {
            points_index[current] = points_index.size();
        }
        
        int j = points_index[current];
        
        // Add edge (normalized to avoid duplicates)
        edges.insert({min(i,j), max(i,j)});
    }
    
    int V = points_index.size();
    int E = edges.size();
    
    // Euler's formula: V - E + F = 2
    // Closed regions = F - 1 = E - V + 1
    int closed_regions = E - V + 1;
    
    cout << closed_regions << endl;
    
    return 0;
}

Time Complexity: $O(N \log V)$ where $N$ is the path length and $V$ is the number of unique vertices.

Space Complexity: $O(V + E)$

Why This Works

The key insight is that our path creates a connected planar graph:

  1. Planar: No edges cross (they meet only at vertices)
  2. Connected: You can reach any visited point from any other
  3. Each edge traversed counts once: We use a set to track unique edges

Euler’s formula holds for any connected planar graph, making it perfect for this problem!

Interactive Visualization

Try it yourself! Enter a path string (using N, S, E, W) and see the closed regions:

Key Takeaways

  1. Graph modeling is powerful: Converting the path to a graph opens up many algorithmic tools
  2. Euler’s formula is elegant: A simple formula replaces complex cycle detection
  3. Problem structure matters: Recognizing planarity was the key insight
  4. Unique edges matter: Using a set to track edges prevents double-counting

Further Reading


Have you encountered other problems where Euler’s formula provides an elegant solution? Share in the comments below!




Enjoy Reading This Article?

Here are some more articles you might like to read next:

  • Google Gemini updates: Flash 1.5, Gemma 2 and Project Astra
  • Displaying External Posts on Your al-folio Blog
  • Bessie and the Lights