Skip to content
Back to skills

Bfs

ASecurity

Breadth-first search — shortest path on unweighted graphs, level-order traversal, and the `visited` discipline that prevents O(2^n) blowups.

  • 3 stars
  • 0 votes
  • 0 copies
  • 1 view
  • Added August 31, 2026
ai-agentsjavascriptpythongojavanode

Works with

  • cli

Security analysis

A100/100

Scanned August 31, 2026

npx -y skills add 0bserver07/chimera --skill bfs --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Bfs?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Bfs
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/0bserver07-bfs/badge)](https://www.skillsdirectory.com/skills/0bserver07-bfs)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: algo-bfs
description: Breadth-first search — shortest path on unweighted graphs, level-order traversal, and the `visited` discipline that prevents O(2^n) blowups.
when-to-use: "Shortest path on unweighted graphs, level traversal, multi-source spread, word-ladder transformations."
---

## Breadth-first search — queue + visited

BFS is the right answer to "shortest number of steps" on an
unweighted graph. The dangerous failure mode is forgetting to mark
nodes visited *when enqueued* — pushing duplicates blows the queue
up exponentially on cyclic graphs.

### Invariants

* The queue holds nodes in non-decreasing distance from the source.
* `visited[v]` is true iff `v` has been enqueued (NOT iff it has
  been dequeued — the difference matters).
* When a node is dequeued, its recorded distance is final and
  correct. No later path can be shorter.
* On unweighted graphs, BFS produces shortest paths. On weighted
  graphs use Dijkstra or 0/1-BFS (deque) instead.

### Complexity

* Time: `O(V + E)` for an adjacency-list representation.
* Space: `O(V)` for the queue and `visited` set.
* Multi-source BFS: same asymptotics — push every source at level
  0, then expand normally.

### Template — Python (grid + multi-source)

```python
from collections import deque

def shortest_grid_path(grid: list[list[int]],
                       starts: list[tuple[int, int]]) -> list[list[int]]:
    """Distance from any start to each cell. ``-1`` if unreachable."""
    rows, cols = len(grid), len(grid[0])
    dist = [[-1] * cols for _ in range(rows)]
    q: deque[tuple[int, int]] = deque()
    for r, c in starts:
        dist[r][c] = 0
        q.append((r, c))
    while q:
        r, c = q.popleft()
        for dr, dc in ((1, 0), (-1, 0), (0, 1), (0, -1)):
            nr, nc = r + dr, c + dc
            if (0 <= nr < rows and 0 <= nc < cols
                    and dist[nr][nc] == -1 and grid[nr][nc] != 1):
                dist[nr][nc] = dist[r][c] + 1
                q.append((nr, nc))
    return dist
```

Note the visited check is `dist[nr][nc] == -1` and is performed
*before* enqueueing — never enqueue the same cell twice.

### Template — JavaScript (level-order, generic graph)

```javascript
function bfsLevels(start, neighbors) {
  const visited = new Set([start]);
  let frontier = [start];
  const levels = [];
  while (frontier.length) {
    levels.push(frontier);
    const next = [];
    for (const u of frontier) {
      for (const v of neighbors(u)) {
        if (!visited.has(v)) { visited.add(v); next.push(v); }
      }
    }
    frontier = next;
  }
  return levels;
}
```

The "two-array level swap" form is more readable than a single
queue with a sentinel when the level boundary matters.

### Common pitfalls

* **Marking visited on dequeue, not enqueue.** Allows duplicate
  pushes; on a graph with branching factor `b` and depth `d` the
  queue grows to `O(b^d)`.
* **Using BFS on weighted graphs.** Edge weight 1 only — anything
  else gives wrong shortest paths. Reach for Dijkstra.
* **Re-pushing for shorter paths.** On unweighted graphs, the first
  time a node is reached IS the shortest. No need to relax.
* **Starting with `q = [start]; visited = {}`.** Mark the source
  visited before the loop, otherwise it can be re-pushed.
* **Big grids with `list.pop(0)` instead of `deque.popleft()`.** O(n)
  per pop — the whole BFS becomes `O(V^2)`.

### Test corner cases

* Single-node graph (start equals goal — distance 0).
* Disconnected graph (some nodes unreachable — distance stays `-1`).
* Cycles (must not loop forever).
* All cells blocked except start.
* Start cell IS the goal.
* Multi-source BFS where two sources race to the same cell — the
  closer source must win.

For shortest *weighted* path, use Dijkstra; for `0/1`-weighted, use
a deque (push-front for 0-weight edges, push-back for 1-weight).

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.