Skip to main content

Operation: Circuit Breaker

When Dfs Meets Bfs: The Grand Rapids Rescue

A Dual-algorithm Emergency Through Artprize Territory

SCROLL TO COMMENCE MISSION ↓


The Midnight Alert

The Grand River glowed electric blue under the pedestrian Blue Bridge as Dr. Nate Chen's phone erupted with an emergency alert. At 11:47 PM on September 23rd, 2026—peak ArtPrize installation week—something catastrophic had happened.

Dr. Nate Chen on the Blue Bridge at night during the emergency alert

Maya Patel, the 28-year-old Indian-American systems architect who'd built the entire ArtPrize visitor routing engine, was panicking from her Heritage Hill Victorian. Her voice cracked through the encrypted call: "Nate, the load balancers are fried. Half a million visitors tomorrow. The navigation system is completely bricked."

Nate grabbed his laptop and sprinted toward his Tesla. "I'm picking up Priya. We're hitting John Ball Zoo first—that's Ground Zero."

Priya Okoye, 26, Filipino-American computer vision specialist, was waiting curbside at her apartment near Frederik Meijer Gardens. She'd been debugging lantern pattern recognition for the Lantern Festival (opening April 2026 at the Zoo) but dropped everything when Maya's alert pinged.

"Nate," Priya said as she jumped in, "Maya's routing engine used a single algorithm. DFS only. It went deep into one neighborhood cluster and never surfaced. We need both—DFS and BFS working together."

The three of them were about to execute what would become legend in Grand Rapids tech circles: Operation Circuit Breaker.


The Crisis at John Ball Zoo

The Zoo's parking lot was chaos. ArtPrize installations were scattered everywhere—glowing sculptures, interactive projections, sound installations. The navigation app was supposed to guide visitors through 200+ venues across the city in the optimal order.

Maya met them at the 30-foot waterfall inside the main exhibit hall, her laptop displaying a catastrophic graph visualization.

"Look at this," she said, pulling up the venue graph. "Each venue is a node. Paths between them are edges. DFS goes deep down one branch before backtracking. BFS explores level by level."

# The BROKEN DFS-Only Approach
def dfs_only(graph, start, target):
visited = set()
stack = [(start, [start])]

while stack:
node, path = stack.pop()
if node == target:
return path
if node not in visited:
visited.add(node)
# DFS: Add neighbors in reverse order (stack behavior)
for neighbor in reversed(graph.get(node, [])):
if neighbor not in visited:
stack.append((neighbor, path + [neighbor]))
return None

"The problem," Priya explained, pulling up visitor heatmaps, "is that DFS finds a path, but not necessarily the optimal path. Visitors are getting routed through Heritage Hill, then all the way to Fulton Street, then back to downtown. It's a nightmare."

Maya Patel at her Heritage Hill Victorian home surrounded by laptop screens showing graph visualizations

Nate leaned forward. "DFS is great for exploration—finding any path through a maze. But BFS guarantees the shortest path in an unweighted graph. We need both."

# BFS for Shortest Path (Unweighted Graph)
from collections import deque

def bfs_shortest_path(graph, start, target):
if start == target:
return [start]

visited = {start}
queue = deque([(start, [start])])

while queue:
node, path = queue.popleft()
# BFS: Explore level by level
for neighbor in graph.get(node, []):
if neighbor not in visited:
if neighbor == target:
return path + [neighbor]
visited.add(neighbor)
queue.append((neighbor, path + [neighbor]))
return None

Maya's eyes widened. "So BFS would find the minimum number of venues between any two points?"

"Exactly," Nate said. "But here's the twist—we need DFS to explore connected components, then BFS to optimize within them."

The team gathered around the 30-foot waterfall at John Ball Zoo with holographic graph visualizations

The Dual-Algorithm Strategy

The team relocated to the rooftop café at John Ball Zoo, overlooking the Grand River. Downtown Grand Rapids sparkled in the distance. ArtPrize installations lit up the historic bridges crossing the river—the 1892 Grand Rapids and Indiana Railroad bridge near Fulton and Pearl.

"Here's the architecture," Nate began, sketching on his tablet. "We use DFS to identify all connected components—clusters of venues that are reachable from each other. Then, within each component, we use BFS to find optimal paths."

The team on the rooftop café at John Ball Zoo overlooking Grand Rapids at dawn with historic bridges visible
# Step 1: DFS to Find Connected Components
def find_connected_components(graph):
visited = set()
components = []

def dfs_component(start, component):
visited.add(start)
component.append(start)
for neighbor in graph.get(start, []):
if neighbor not in visited:
dfs_component(start=neighbor, component=component)

for node in graph:
if node not in visited:
component = []
dfs_component(node, component)
components.append(component)

return components

# Step 2: BFS for Optimal Paths Within Components
def optimize_component_paths(graph, components):
optimized_routes = {}

for component in components:
# For each component, find optimal paths between all pairs
for start in component:
optimized_routes[start] = {}
for target in component:
if start != target:
path = bfs_shortest_path(graph, start, target)
optimized_routes[start][target] = path

return optimized_routes

Priya was already coding. "I'm integrating this with the real-time crowd data. If a venue is at capacity, we dynamically reroute using the next-best BFS path."

# Complete Dual-Algorithm Router
class ArtPrizeRouter:
def __init__(self, venue_graph):
self.graph = venue_graph
self.components = find_connected_components(venue_graph)
self.optimized_routes = optimize_component_paths(venue_graph, self.components)

def get_optimal_route(self, start, target, avoid=[]):
"""
Get optimal route from start to target, avoiding specified venues.
Uses DFS for component awareness, BFS for path optimization.
"""
# Check if start and target are in the same component
for component in self.components:
if start in component and target in component:
# Same component: BFS guarantees shortest path
base_path = self.optimized_routes.get(start, {}).get(target)
if base_path:
# Filter out avoided venues
return [v for v in base_path if v not in avoid]

# Different components: No path exists
return None

def get_all_venues_in_component(self, venue):
"""Return all venues reachable from the given venue."""
for component in self.components:
if venue in component:
return component
return []

Maya checked her watch: 3:17 AM. "The World of Winter Festival team just pinged—they want to integrate this for their ice sculpture tour in January. Can we make it generic enough for any Grand Rapids event?"

Nate grinned. "That's the plan. This isn't just for ArtPrize. This is for the Lantern Festival at John Ball Zoo. This is for the Oddities & Curiousities Expo. This is for every festival from March to December."


The Grand Rapids Test

Dawn broke over Heritage Hill as the team deployed the code. The historic neighborhood—with its 135+ historic homes showcasing Victorian, Colonial Revival, and Craftsman architecture—was the perfect test case. Narrow streets, one-way roads, dead ends.

"Running the simulation," Priya announced. "Loading venue graph: 200 nodes, 450 edges. Starting dual-algorithm routing."

Priya Okoye coding intensely with Python DFS and BFS code on screen, downtown Grand Rapids in background
# Real-World Venue Graph (Simplified Grand Rapids Map)
grand_rapids_venues = {
'john_ball_zoo': ['heritage_hill', 'downtown_core', 'meijer_gardens'],
'heritage_hill': ['john_ball_zoo', 'downtown_core', 'fulton_street'],
'downtown_core': ['john_ball_zoo', 'heritage_hill', 'blue_bridge', 'artprize_hub'],
'blue_bridge': ['downtown_core', 'artprize_hub', 'railroad_bridge'],
'fulton_street': ['heritage_hill', 'railroad_bridge', 'pearl_street'],
'railroad_bridge': ['blue_bridge', 'fulton_street', 'pearl_street'],
'pearl_street': ['fulton_street', 'railroad_bridge'],
'meijer_gardens': ['john_ball_zoo', 'east_grand_rapids'],
'east_grand_rapids': ['meijer_gardens'],
'artprize_hub': ['downtown_core', 'blue_bridge'],
}

# Initialize the router
router = ArtPrizeRouter(grand_rapids_venues)

# Test Case 1: Find optimal route from Zoo to ArtPrize Hub
route = router.get_optimal_route('john_ball_zoo', 'artprize_hub')
print(f"Optimal Route: {' -> '.join(route)}")
# Output: john_ball_zoo -> downtown_core -> artprize_hub

# Test Case 2: Find all venues in the same component
component = router.get_all_venues_in_component('heritage_hill')
print(f"Connected Venues: {len(component)} venues reachable")
# Output: 10 venues reachable (all venues are connected in this graph)

The simulation ran. The old DFS-only system had visitors taking 8-12 venue hops to cross downtown. The new dual-algorithm system? Maximum 3 hops.

Heritage Hill historic neighborhood with visitors using the navigation app successfully

Maya let out a whoop. "We just cut average visitor travel time by 60%! The Gerald R. Ford Museum crowd can hit the Grand Rapids Public Museum in two stops. The Meyer May House tour connects directly to the Blue Bridge installations."

But Priya spotted an edge case. "What if a venue gets removed mid-day? Weather closure? Technical issue?"

Nate was already typing. "Dynamic graph updates. We rebuild the affected component incrementally."

# Dynamic Graph Updates
class DynamicArtPrizeRouter(ArtPrizeRouter):
def remove_venue(self, venue):
"""Remove a venue from the graph (e.g., weather closure)."""
# Remove from graph
if venue in self.graph:
del self.graph[venue]

# Remove from all neighbor lists
for neighbors in self.graph.values():
if venue in neighbors:
neighbors.remove(venue)

# Rebuild components and routes
self.components = find_connected_components(self.graph)
self.optimized_routes = optimize_component_paths(self.graph, self.components)

return True

def add_venue(self, venue, connections):
"""Add a new venue with its connections."""
self.graph[venue] = connections

# Update neighbor lists
for neighbor in connections:
if neighbor in self.graph:
self.graph[neighbor].append(venue)

# Rebuild components and routes
self.components = find_connected_components(self.graph)
self.optimized_routes = optimize_component_paths(self.graph, self.components)

return True

"Test it," Maya said. "Remove the Blue Bridge—simulate maintenance closure."

Priya typed the command. The system recalculated in 47 milliseconds. Routes updated. No visitors stranded.

"Perfect," Nate said. "Now deploy to production."


The Victory Lap

By 9:00 AM, the system was live. ArtPrize visitors flooded in from across Michigan—Chicago, Detroit, Lansing. The navigation app hummed smoothly, routing half a million people through the city's cultural landmarks.

The team watched from the Frederik Meijer Gardens sculpture park, surrounded by Dale Chihuly's glass installations. The Butterflies Are Blooming exhibition would open in March 2026, and they'd already integrated the routing system for that too.

The team celebrating successful deployment at Meijer Gardens sculpture park with colorful glass art

"You know what we proved?" Priya said, sipping her coffee. "DFS alone is like exploring without a map. BFS alone is efficient but blind to the bigger structure. Together?"

"Together," Maya finished, "they see the forest and the trees."

Nate pulled up the final metrics on his phone:

  • Average route length: Reduced from 7.2 hops to 2.8 hops
  • Visitor satisfaction: Up 43%
  • Venue coverage: 94% of visitors hitting 5+ venues (was 61%)
  • System uptime: 99.97%
Close-up of smartphone showing victory metrics dashboard with 60 percent reduction and 94 percent coverage

"The Grand Rapids Lantern Festival team just signed on," Maya said. "April through June at John Ball Zoo. They want the same routing for their 50+ hand-crafted lantern displays."

"And World of Winter," Priya added. "January ice sculpture tour. We're booking solid through 2026."

Nate smiled, watching the sunlight hit the Grand River. "This is what we do. We don't just solve algorithms. We solve cities."

# The Final Unified Solution
def hybrid_dfs_bfs_router(graph, start, targets):
"""
Production-ready hybrid router for Grand Rapids events.
Uses DFS for exploration, BFS for optimization.

Args:
graph: Dict mapping venue -> list of connected venues
start: Starting venue
targets: List of target venues to visit

Returns:
Optimal route visiting all targets (if possible)
"""
from collections import deque

# Step 1: Use DFS to verify all targets are reachable
def dfs_reachable(start, target):
visited = set()
stack = [start]
while stack:
node = stack.pop()
if node == target:
return True
if node not in visited:
visited.add(node)
stack.extend(graph.get(node, []))
return False

# Verify all targets are reachable
for target in targets:
if not dfs_reachable(start, target):
raise ValueError(f"Target {target} is not reachable from {start}")

# Step 2: Use BFS to find shortest path to each target
def bfs_path(start, end):
queue = deque([(start, [start])])
visited = {start}
while queue:
node, path = queue.popleft()
for neighbor in graph.get(node, []):
if neighbor not in visited:
if neighbor == end:
return path + [neighbor]
visited.add(neighbor)
queue.append((neighbor, path + [neighbor]))
return None

# Build optimal route visiting all targets
route = [start]
current = start
remaining = targets.copy()

while remaining:
# Find nearest target using BFS
nearest = None
shortest_path = None

for target in remaining:
path = bfs_path(current, target)
if path and (shortest_path is None or len(path) < len(shortest_path)):
nearest = target
shortest_path = path

if nearest is None:
break

# Add path to route (excluding current position)
route.extend(shortest_path[1:])
current = nearest
remaining.remove(nearest)

return route

# Usage: Plan a full ArtPrize tour
tour_route = hybrid_dfs_bfs_router(
grand_rapids_venues,
start='john_ball_zoo',
targets=['artprize_hub', 'blue_bridge', 'heritage_hill']
)
print(f"Complete Tour: {' -> '.join(tour_route)}")
Epic panoramic view of Grand Rapids at sunset with glowing flow lines connecting venues across the city

The three of them stood there—Dr. Nate Chen, Maya Patel, Priya Okoye—watching visitors flow through Grand Rapids like a perfectly optimized graph traversal.

DFS had given them the courage to explore deep. BFS had given them the wisdom to find what was closest. Together, they'd built something that would guide thousands through the art, culture, and beauty of a city that never stopped innovating.

Mission Complete.


Technical Deep Dive

When to Use DFS vs BFS

ScenarioAlgorithmWhy
Finding any pathDFSLower memory, faster to first solution
Finding shortest path (unweighted)BFSLevel-by-level guarantees minimum hops
Exploring all possibilitiesDFSNatural backtracking for exhaustive search
Finding connected componentsDFSRecursive structure is elegant
Level-order processingBFSInherent level structure
Memory-constrained environmentsDFSO(h) vs O(w) where h=height, w=width

Complexity Analysis

"""
Time Complexity:
- DFS: O(V + E) where V = vertices, E = edges
- BFS: O(V + E) where V = vertices, E = edges
- Hybrid (this solution): O(V + E) for component finding + O(V * (V + E)) for all-pairs BFS

Space Complexity:
- DFS: O(V) for visited set + O(h) for recursion/stack
- BFS: O(V) for visited set + O(V) for queue
- Hybrid: O(V²) for storing all-pairs routes

Where This Shines:
- Event routing (ArtPrize, festivals, tours)
- Network packet routing
- Social network connection analysis
- Dependency resolution with optimization
"""

Your Mission

Build a routing system for your city's next major event. Use the dual-algorithm approach:

  1. DFS to map the territory
  2. BFS to optimize the paths
  3. Dynamic updates to handle real-world chaos

The code is your starter rig. Grand Rapids is your testbed. The world is your graph.

Go make connections.