{
  "id": "graphs/a-star",
  "version": 1,
  "deterministic": true,
  "url": "/dsa/graphs/a-star",
  "topic": {
    "slug": "graphs",
    "title": "Graphs"
  },
  "title": "A* Search",
  "tagline": "Dijkstra with a sense of direction — it guesses what's left, and aims.",
  "vizKind": "graph",
  "complexity": {
    "time": {
      "best": "O(E)",
      "average": "O(E log V)",
      "worst": "O(E log V)"
    },
    "space": "O(V)",
    "growth": "nlogn",
    "note": "The same worst case as Dijkstra — with a useless heuristic it degrades to exactly Dijkstra. In practice a good heuristic slashes the number of nodes expanded, often dramatically. The complexity class doesn't change; the real-world work does."
  },
  "code": {
    "javascript": "// Dijkstra explores in every direction. A* aims.\nfunction aStar(graph, start, goal) {\n  const g = {};                     // real cost from the start\n  for (const v of graph.nodes) g[v] = Infinity;\n  g[start] = 0;\n\n  const open = new PriorityQueue();\n  // f = what it cost to get here + a GUESS of what's left\n  open.push(start, h(start, goal));\n\n  while (!open.isEmpty()) {\n    const u = open.pop();           // lowest f, not lowest g\n    if (u === goal) return g[goal];\n\n    for (const [v, w] of graph.edges[u]) {\n      if (g[u] + w < g[v]) {\n        g[v] = g[u] + w;\n        open.push(v, g[v] + h(v, goal));   // f = g + h\n      }\n    }\n  }\n  return Infinity;\n}",
    "python": "# Dijkstra explores in every direction. A* aims.\nimport heapq\n\ndef a_star(graph, start, goal):\n    g = {v: float('inf') for v in graph}   # real cost from the start\n    g[start] = 0\n\n    # f = what it cost to get here + a GUESS of what's left\n    open_set = [(h(start, goal), start)]\n\n    while open_set:\n        _, u = heapq.heappop(open_set)     # lowest f, not lowest g\n        if u == goal: return g[goal]\n\n        for v, w in graph[u]:\n            if g[u] + w < g[v]:\n                g[v] = g[u] + w\n                heapq.heappush(open_set, (g[v] + h(v, goal), v))  # f = g + h\n\n    return float('inf')\n",
    "java": "// Dijkstra explores in every direction. A* aims.\nint aStar(Graph graph, String start, String goal) {\n  Map<String,Integer> g = new HashMap<>();  // real cost from the start\n  for (String v : graph.nodes) g.put(v, INF);\n  g.put(start, 0);\n\n  PriorityQueue<Node> open = new PriorityQueue<>();\n  // f = what it cost to get here + a GUESS of what's left\n  open.add(new Node(start, h(start, goal)));\n\n  while (!open.isEmpty()) {\n    String u = open.poll().id;              // lowest f, not lowest g\n    if (u.equals(goal)) return g.get(goal);\n\n    for (Edge e : graph.edges.get(u)) {\n      if (g.get(u) + e.w < g.get(e.to)) {\n        g.put(e.to, g.get(u) + e.w);\n        open.add(new Node(e.to, g.get(e.to) + h(e.to, goal)));  // f = g + h\n      }\n    }\n  }\n  return INF;\n}",
    "cpp": "// Dijkstra explores in every direction. A* aims.\nint aStar(Graph& graph, string start, string goal) {\n  map<string,int> g;                 // real cost from the start\n  for (auto& v : graph.nodes) g[v] = INF;\n  g[start] = 0;\n\n  priority_queue<pair<int,string>, vector<pair<int,string>>, greater<>> open;\n  // f = what it cost to get here + a GUESS of what's left\n  open.push({h(start, goal), start});\n\n  while (!open.empty()) {\n    auto [f, u] = open.top(); open.pop();   // lowest f, not lowest g\n    if (u == goal) return g[goal];\n\n    for (auto& [v, w] : graph.edges[u]) {\n      if (g[u] + w < g[v]) {\n        g[v] = g[u] + w;\n        open.push({g[v] + h(v, goal), v});  // f = g + h\n      }\n    }\n  }\n  return INF;\n}"
  },
  "defaultInput": [
    1
  ],
  "defaultTarget": null,
  "inputHint": "Each node shows g + h — the real cost so far, plus the guess of what's left.",
  "pitfalls": [
    {
      "wrong": "Using a heuristic that overestimates.",
      "right": "Then A* can discard the genuinely best route because it guessed wrongly that the route was expensive. It stays fast and becomes wrong. The heuristic MUST be optimistic."
    },
    {
      "wrong": "Expanding on the lowest g instead of the lowest f.",
      "right": "That's just Dijkstra with extra steps. The whole point is to prioritise by g + h, so the guess actually steers the search."
    },
    {
      "wrong": "Using A* when there's no meaningful heuristic.",
      "right": "If you can't estimate the remaining distance, h = 0 — and A* is precisely Dijkstra. Use A* when the problem has real geometry to exploit."
    },
    {
      "wrong": "Thinking A* has a better Big-O than Dijkstra.",
      "right": "It doesn't. Same worst case. What it improves is how many nodes it actually expands in practice, which is often the difference that matters."
    }
  ],
  "quiz": [
    {
      "q": "What is f in A*?",
      "options": [
        "The cost so far",
        "g + h — the real cost to get here, plus the estimated cost still to go",
        "The number of nodes expanded",
        "The final answer"
      ],
      "answer": 1,
      "why": "f = g + h. A* always expands the node with the smallest f, which is what makes it head towards the goal rather than spreading out blindly in all directions."
    },
    {
      "q": "What must be true of the heuristic for A* to stay correct?",
      "options": [
        "It must be exact",
        "It must never overestimate the remaining distance — it has to be optimistic",
        "It must be large",
        "It must be zero"
      ],
      "answer": 1,
      "why": "An optimistic (admissible) heuristic keeps A* provably correct. Overestimate, and it can throw away the true best route because it wrongly guessed that route was expensive."
    },
    {
      "q": "You set h = 0 for every node. What is A* now?",
      "options": [
        "Broken",
        "Exactly Dijkstra's algorithm",
        "Breadth-first search",
        "Faster than before"
      ],
      "answer": 1,
      "why": "With no guess, f = g, and A* expands purely by cost-so-far — which is Dijkstra, precisely. The guess is the entire difference between the two algorithms."
    }
  ],
  "problems": [
    {
      "name": "Shortest Path in Binary Matrix",
      "difficulty": "Medium",
      "url": "https://leetcode.com/problems/shortest-path-in-binary-matrix/"
    },
    {
      "name": "Sliding Puzzle",
      "difficulty": "Hard",
      "url": "https://leetcode.com/problems/sliding-puzzle/"
    },
    {
      "name": "Minimum Knight Moves",
      "difficulty": "Medium",
      "url": "https://leetcode.com/problems/minimum-knight-moves/"
    }
  ],
  "trace": {
    "note": "Each frame is one immutable step: data snapshot, pointers, per-index roles, executing code line, and a one-sentence explanation.",
    "length": 19,
    "frames": [
      {
        "data": {
          "nodes": [
            {
              "id": "S",
              "label": "S 0+9",
              "x": 0.08,
              "y": 0.5,
              "role": "active"
            },
            {
              "id": "A",
              "label": "A ∞+7",
              "x": 0.3,
              "y": 0.18
            },
            {
              "id": "B",
              "label": "B ∞+7",
              "x": 0.3,
              "y": 0.82
            },
            {
              "id": "C",
              "label": "C ∞+4",
              "x": 0.52,
              "y": 0.5
            },
            {
              "id": "D",
              "label": "D ∞+6",
              "x": 0.52,
              "y": 0.1
            },
            {
              "id": "E",
              "label": "E ∞+3",
              "x": 0.74,
              "y": 0.75
            },
            {
              "id": "F",
              "label": "F ∞+3",
              "x": 0.74,
              "y": 0.3
            },
            {
              "id": "G",
              "label": "G ∞+0",
              "x": 0.94,
              "y": 0.5
            }
          ],
          "edges": [
            {
              "from": "S",
              "to": "A",
              "weight": 3
            },
            {
              "from": "S",
              "to": "B",
              "weight": 2
            },
            {
              "from": "A",
              "to": "D",
              "weight": 4
            },
            {
              "from": "A",
              "to": "C",
              "weight": 3
            },
            {
              "from": "B",
              "to": "C",
              "weight": 4
            },
            {
              "from": "B",
              "to": "E",
              "weight": 6
            },
            {
              "from": "C",
              "to": "F",
              "weight": 3
            },
            {
              "from": "D",
              "to": "F",
              "weight": 5
            },
            {
              "from": "E",
              "to": "G",
              "weight": 4
            },
            {
              "from": "F",
              "to": "G",
              "weight": 2
            }
          ],
          "directed": false,
          "frontier": {
            "label": "queue",
            "ids": [
              "S"
            ]
          },
          "visited": []
        },
        "pointers": [],
        "highlights": [],
        "codeLine": 8,
        "variables": {
          "start": "S",
          "goal": "G",
          "note": "labels show g + h"
        },
        "explanation": "Get from S to G. Each node shows two numbers: **g**, what it actually cost to reach it, and **h**, a straight-line *guess* of what's left. A* always expands the node with the smallest g + h — so it aims at the goal instead of spreading out blindly like Dijkstra.",
        "stats": {
          "comparisons": 0,
          "swaps": 0
        },
        "accent": "active"
      },
      {
        "data": {
          "nodes": [
            {
              "id": "S",
              "label": "S 0+9",
              "x": 0.08,
              "y": 0.5,
              "role": "sorted"
            },
            {
              "id": "A",
              "label": "A ∞+7",
              "x": 0.3,
              "y": 0.18
            },
            {
              "id": "B",
              "label": "B ∞+7",
              "x": 0.3,
              "y": 0.82
            },
            {
              "id": "C",
              "label": "C ∞+4",
              "x": 0.52,
              "y": 0.5
            },
            {
              "id": "D",
              "label": "D ∞+6",
              "x": 0.52,
              "y": 0.1
            },
            {
              "id": "E",
              "label": "E ∞+3",
              "x": 0.74,
              "y": 0.75
            },
            {
              "id": "F",
              "label": "F ∞+3",
              "x": 0.74,
              "y": 0.3
            },
            {
              "id": "G",
              "label": "G ∞+0",
              "x": 0.94,
              "y": 0.5
            }
          ],
          "edges": [
            {
              "from": "S",
              "to": "A",
              "weight": 3
            },
            {
              "from": "S",
              "to": "B",
              "weight": 2
            },
            {
              "from": "A",
              "to": "D",
              "weight": 4
            },
            {
              "from": "A",
              "to": "C",
              "weight": 3
            },
            {
              "from": "B",
              "to": "C",
              "weight": 4
            },
            {
              "from": "B",
              "to": "E",
              "weight": 6
            },
            {
              "from": "C",
              "to": "F",
              "weight": 3
            },
            {
              "from": "D",
              "to": "F",
              "weight": 5
            },
            {
              "from": "E",
              "to": "G",
              "weight": 4
            },
            {
              "from": "F",
              "to": "G",
              "weight": 2
            }
          ],
          "directed": false,
          "frontier": {
            "label": "queue",
            "ids": []
          },
          "visited": [
            "S"
          ]
        },
        "pointers": [],
        "highlights": [],
        "codeLine": 12,
        "variables": {
          "expanding": "S",
          "g": "0",
          "h": 9,
          "f": 9
        },
        "explanation": "Expand S: it has the lowest f = g + h = 0 + 9 = 9. Dijkstra would have picked purely on g and might have gone the wrong way; the h term is what makes A* aim.",
        "stats": {
          "comparisons": 1,
          "swaps": 0
        },
        "accent": "sorted"
      },
      {
        "data": {
          "nodes": [
            {
              "id": "S",
              "label": "S 0+9",
              "x": 0.08,
              "y": 0.5,
              "role": "sorted"
            },
            {
              "id": "A",
              "label": "A ∞+7",
              "x": 0.3,
              "y": 0.18,
              "role": "compare"
            },
            {
              "id": "B",
              "label": "B ∞+7",
              "x": 0.3,
              "y": 0.82
            },
            {
              "id": "C",
              "label": "C ∞+4",
              "x": 0.52,
              "y": 0.5
            },
            {
              "id": "D",
              "label": "D ∞+6",
              "x": 0.52,
              "y": 0.1
            },
            {
              "id": "E",
              "label": "E ∞+3",
              "x": 0.74,
              "y": 0.75
            },
            {
              "id": "F",
              "label": "F ∞+3",
              "x": 0.74,
              "y": 0.3
            },
            {
              "id": "G",
              "label": "G ∞+0",
              "x": 0.94,
              "y": 0.5
            }
          ],
          "edges": [
            {
              "from": "S",
              "to": "A",
              "weight": 3,
              "role": "compare"
            },
            {
              "from": "S",
              "to": "B",
              "weight": 2
            },
            {
              "from": "A",
              "to": "D",
              "weight": 4
            },
            {
              "from": "A",
              "to": "C",
              "weight": 3
            },
            {
              "from": "B",
              "to": "C",
              "weight": 4
            },
            {
              "from": "B",
              "to": "E",
              "weight": 6
            },
            {
              "from": "C",
              "to": "F",
              "weight": 3
            },
            {
              "from": "D",
              "to": "F",
              "weight": 5
            },
            {
              "from": "E",
              "to": "G",
              "weight": 4
            },
            {
              "from": "F",
              "to": "G",
              "weight": 2
            }
          ],
          "directed": false,
          "frontier": {
            "label": "queue",
            "ids": []
          },
          "visited": [
            "S"
          ]
        },
        "pointers": [],
        "highlights": [],
        "codeLine": 16,
        "variables": {
          "from": "S",
          "to": "A",
          "edge": 3,
          "via": 3,
          "known": "∞",
          "h": 7
        },
        "explanation": "S → A costs 0 + 3 = 3, better than the ∞ we had. Update g(A) = 3, so f(A) = 3 + 7 = 10.",
        "stats": {
          "comparisons": 2,
          "swaps": 0
        },
        "accent": "found"
      },
      {
        "data": {
          "nodes": [
            {
              "id": "S",
              "label": "S 0+9",
              "x": 0.08,
              "y": 0.5,
              "role": "sorted"
            },
            {
              "id": "A",
              "label": "A 3+7",
              "x": 0.3,
              "y": 0.18,
              "role": "pivot"
            },
            {
              "id": "B",
              "label": "B ∞+7",
              "x": 0.3,
              "y": 0.82,
              "role": "compare"
            },
            {
              "id": "C",
              "label": "C ∞+4",
              "x": 0.52,
              "y": 0.5
            },
            {
              "id": "D",
              "label": "D ∞+6",
              "x": 0.52,
              "y": 0.1
            },
            {
              "id": "E",
              "label": "E ∞+3",
              "x": 0.74,
              "y": 0.75
            },
            {
              "id": "F",
              "label": "F ∞+3",
              "x": 0.74,
              "y": 0.3
            },
            {
              "id": "G",
              "label": "G ∞+0",
              "x": 0.94,
              "y": 0.5
            }
          ],
          "edges": [
            {
              "from": "S",
              "to": "A",
              "weight": 3,
              "role": "sorted"
            },
            {
              "from": "S",
              "to": "B",
              "weight": 2,
              "role": "compare"
            },
            {
              "from": "A",
              "to": "D",
              "weight": 4
            },
            {
              "from": "A",
              "to": "C",
              "weight": 3
            },
            {
              "from": "B",
              "to": "C",
              "weight": 4
            },
            {
              "from": "B",
              "to": "E",
              "weight": 6
            },
            {
              "from": "C",
              "to": "F",
              "weight": 3
            },
            {
              "from": "D",
              "to": "F",
              "weight": 5
            },
            {
              "from": "E",
              "to": "G",
              "weight": 4
            },
            {
              "from": "F",
              "to": "G",
              "weight": 2
            }
          ],
          "directed": false,
          "frontier": {
            "label": "queue",
            "ids": [
              "A"
            ]
          },
          "visited": [
            "S"
          ]
        },
        "pointers": [],
        "highlights": [],
        "codeLine": 16,
        "variables": {
          "from": "S",
          "to": "B",
          "edge": 2,
          "via": 2,
          "known": "∞",
          "h": 7
        },
        "explanation": "S → B costs 0 + 2 = 2, better than the ∞ we had. Update g(B) = 2, so f(B) = 2 + 7 = 9.",
        "stats": {
          "comparisons": 3,
          "swaps": 1
        },
        "accent": "found"
      },
      {
        "data": {
          "nodes": [
            {
              "id": "S",
              "label": "S 0+9",
              "x": 0.08,
              "y": 0.5,
              "role": "sorted"
            },
            {
              "id": "A",
              "label": "A 3+7",
              "x": 0.3,
              "y": 0.18,
              "role": "pivot"
            },
            {
              "id": "B",
              "label": "B 2+7",
              "x": 0.3,
              "y": 0.82,
              "role": "sorted"
            },
            {
              "id": "C",
              "label": "C ∞+4",
              "x": 0.52,
              "y": 0.5
            },
            {
              "id": "D",
              "label": "D ∞+6",
              "x": 0.52,
              "y": 0.1
            },
            {
              "id": "E",
              "label": "E ∞+3",
              "x": 0.74,
              "y": 0.75
            },
            {
              "id": "F",
              "label": "F ∞+3",
              "x": 0.74,
              "y": 0.3
            },
            {
              "id": "G",
              "label": "G ∞+0",
              "x": 0.94,
              "y": 0.5
            }
          ],
          "edges": [
            {
              "from": "S",
              "to": "A",
              "weight": 3,
              "role": "sorted"
            },
            {
              "from": "S",
              "to": "B",
              "weight": 2,
              "role": "sorted"
            },
            {
              "from": "A",
              "to": "D",
              "weight": 4
            },
            {
              "from": "A",
              "to": "C",
              "weight": 3
            },
            {
              "from": "B",
              "to": "C",
              "weight": 4
            },
            {
              "from": "B",
              "to": "E",
              "weight": 6
            },
            {
              "from": "C",
              "to": "F",
              "weight": 3
            },
            {
              "from": "D",
              "to": "F",
              "weight": 5
            },
            {
              "from": "E",
              "to": "G",
              "weight": 4
            },
            {
              "from": "F",
              "to": "G",
              "weight": 2
            }
          ],
          "directed": false,
          "frontier": {
            "label": "queue",
            "ids": [
              "A"
            ]
          },
          "visited": [
            "S",
            "B"
          ]
        },
        "pointers": [],
        "highlights": [],
        "codeLine": 12,
        "variables": {
          "expanding": "B",
          "g": "2",
          "h": 7,
          "f": 9
        },
        "explanation": "Expand B: it has the lowest f = g + h = 2 + 7 = 9. Dijkstra would have picked purely on g and might have gone the wrong way; the h term is what makes A* aim.",
        "stats": {
          "comparisons": 4,
          "swaps": 2
        },
        "accent": "sorted"
      },
      {
        "data": {
          "nodes": [
            {
              "id": "S",
              "label": "S 0+9",
              "x": 0.08,
              "y": 0.5,
              "role": "sorted"
            },
            {
              "id": "A",
              "label": "A 3+7",
              "x": 0.3,
              "y": 0.18,
              "role": "pivot"
            },
            {
              "id": "B",
              "label": "B 2+7",
              "x": 0.3,
              "y": 0.82,
              "role": "sorted"
            },
            {
              "id": "C",
              "label": "C ∞+4",
              "x": 0.52,
              "y": 0.5,
              "role": "compare"
            },
            {
              "id": "D",
              "label": "D ∞+6",
              "x": 0.52,
              "y": 0.1
            },
            {
              "id": "E",
              "label": "E ∞+3",
              "x": 0.74,
              "y": 0.75
            },
            {
              "id": "F",
              "label": "F ∞+3",
              "x": 0.74,
              "y": 0.3
            },
            {
              "id": "G",
              "label": "G ∞+0",
              "x": 0.94,
              "y": 0.5
            }
          ],
          "edges": [
            {
              "from": "S",
              "to": "A",
              "weight": 3,
              "role": "sorted"
            },
            {
              "from": "S",
              "to": "B",
              "weight": 2,
              "role": "sorted"
            },
            {
              "from": "A",
              "to": "D",
              "weight": 4
            },
            {
              "from": "A",
              "to": "C",
              "weight": 3
            },
            {
              "from": "B",
              "to": "C",
              "weight": 4,
              "role": "compare"
            },
            {
              "from": "B",
              "to": "E",
              "weight": 6
            },
            {
              "from": "C",
              "to": "F",
              "weight": 3
            },
            {
              "from": "D",
              "to": "F",
              "weight": 5
            },
            {
              "from": "E",
              "to": "G",
              "weight": 4
            },
            {
              "from": "F",
              "to": "G",
              "weight": 2
            }
          ],
          "directed": false,
          "frontier": {
            "label": "queue",
            "ids": [
              "A"
            ]
          },
          "visited": [
            "S",
            "B"
          ]
        },
        "pointers": [],
        "highlights": [],
        "codeLine": 16,
        "variables": {
          "from": "B",
          "to": "C",
          "edge": 4,
          "via": 6,
          "known": "∞",
          "h": 4
        },
        "explanation": "B → C costs 2 + 4 = 6, better than the ∞ we had. Update g(C) = 6, so f(C) = 6 + 4 = 10.",
        "stats": {
          "comparisons": 5,
          "swaps": 2
        },
        "accent": "found"
      },
      {
        "data": {
          "nodes": [
            {
              "id": "S",
              "label": "S 0+9",
              "x": 0.08,
              "y": 0.5,
              "role": "sorted"
            },
            {
              "id": "A",
              "label": "A 3+7",
              "x": 0.3,
              "y": 0.18,
              "role": "pivot"
            },
            {
              "id": "B",
              "label": "B 2+7",
              "x": 0.3,
              "y": 0.82,
              "role": "sorted"
            },
            {
              "id": "C",
              "label": "C 6+4",
              "x": 0.52,
              "y": 0.5,
              "role": "pivot"
            },
            {
              "id": "D",
              "label": "D ∞+6",
              "x": 0.52,
              "y": 0.1
            },
            {
              "id": "E",
              "label": "E ∞+3",
              "x": 0.74,
              "y": 0.75,
              "role": "compare"
            },
            {
              "id": "F",
              "label": "F ∞+3",
              "x": 0.74,
              "y": 0.3
            },
            {
              "id": "G",
              "label": "G ∞+0",
              "x": 0.94,
              "y": 0.5
            }
          ],
          "edges": [
            {
              "from": "S",
              "to": "A",
              "weight": 3,
              "role": "sorted"
            },
            {
              "from": "S",
              "to": "B",
              "weight": 2,
              "role": "sorted"
            },
            {
              "from": "A",
              "to": "D",
              "weight": 4
            },
            {
              "from": "A",
              "to": "C",
              "weight": 3
            },
            {
              "from": "B",
              "to": "C",
              "weight": 4,
              "role": "sorted"
            },
            {
              "from": "B",
              "to": "E",
              "weight": 6,
              "role": "compare"
            },
            {
              "from": "C",
              "to": "F",
              "weight": 3
            },
            {
              "from": "D",
              "to": "F",
              "weight": 5
            },
            {
              "from": "E",
              "to": "G",
              "weight": 4
            },
            {
              "from": "F",
              "to": "G",
              "weight": 2
            }
          ],
          "directed": false,
          "frontier": {
            "label": "queue",
            "ids": [
              "A",
              "C"
            ]
          },
          "visited": [
            "S",
            "B"
          ]
        },
        "pointers": [],
        "highlights": [],
        "codeLine": 16,
        "variables": {
          "from": "B",
          "to": "E",
          "edge": 6,
          "via": 8,
          "known": "∞",
          "h": 3
        },
        "explanation": "B → E costs 2 + 6 = 8, better than the ∞ we had. Update g(E) = 8, so f(E) = 8 + 3 = 11.",
        "stats": {
          "comparisons": 6,
          "swaps": 3
        },
        "accent": "found"
      },
      {
        "data": {
          "nodes": [
            {
              "id": "S",
              "label": "S 0+9",
              "x": 0.08,
              "y": 0.5,
              "role": "sorted"
            },
            {
              "id": "A",
              "label": "A 3+7",
              "x": 0.3,
              "y": 0.18,
              "role": "sorted"
            },
            {
              "id": "B",
              "label": "B 2+7",
              "x": 0.3,
              "y": 0.82,
              "role": "sorted"
            },
            {
              "id": "C",
              "label": "C 6+4",
              "x": 0.52,
              "y": 0.5,
              "role": "pivot"
            },
            {
              "id": "D",
              "label": "D ∞+6",
              "x": 0.52,
              "y": 0.1
            },
            {
              "id": "E",
              "label": "E 8+3",
              "x": 0.74,
              "y": 0.75,
              "role": "pivot"
            },
            {
              "id": "F",
              "label": "F ∞+3",
              "x": 0.74,
              "y": 0.3
            },
            {
              "id": "G",
              "label": "G ∞+0",
              "x": 0.94,
              "y": 0.5
            }
          ],
          "edges": [
            {
              "from": "S",
              "to": "A",
              "weight": 3,
              "role": "sorted"
            },
            {
              "from": "S",
              "to": "B",
              "weight": 2,
              "role": "sorted"
            },
            {
              "from": "A",
              "to": "D",
              "weight": 4
            },
            {
              "from": "A",
              "to": "C",
              "weight": 3
            },
            {
              "from": "B",
              "to": "C",
              "weight": 4,
              "role": "sorted"
            },
            {
              "from": "B",
              "to": "E",
              "weight": 6,
              "role": "sorted"
            },
            {
              "from": "C",
              "to": "F",
              "weight": 3
            },
            {
              "from": "D",
              "to": "F",
              "weight": 5
            },
            {
              "from": "E",
              "to": "G",
              "weight": 4
            },
            {
              "from": "F",
              "to": "G",
              "weight": 2
            }
          ],
          "directed": false,
          "frontier": {
            "label": "queue",
            "ids": [
              "C",
              "E"
            ]
          },
          "visited": [
            "S",
            "B",
            "A"
          ]
        },
        "pointers": [],
        "highlights": [],
        "codeLine": 12,
        "variables": {
          "expanding": "A",
          "g": "3",
          "h": 7,
          "f": 10
        },
        "explanation": "Expand A: it has the lowest f = g + h = 3 + 7 = 10. Dijkstra would have picked purely on g and might have gone the wrong way; the h term is what makes A* aim.",
        "stats": {
          "comparisons": 7,
          "swaps": 4
        },
        "accent": "sorted"
      },
      {
        "data": {
          "nodes": [
            {
              "id": "S",
              "label": "S 0+9",
              "x": 0.08,
              "y": 0.5,
              "role": "sorted"
            },
            {
              "id": "A",
              "label": "A 3+7",
              "x": 0.3,
              "y": 0.18,
              "role": "sorted"
            },
            {
              "id": "B",
              "label": "B 2+7",
              "x": 0.3,
              "y": 0.82,
              "role": "sorted"
            },
            {
              "id": "C",
              "label": "C 6+4",
              "x": 0.52,
              "y": 0.5,
              "role": "pivot"
            },
            {
              "id": "D",
              "label": "D ∞+6",
              "x": 0.52,
              "y": 0.1,
              "role": "compare"
            },
            {
              "id": "E",
              "label": "E 8+3",
              "x": 0.74,
              "y": 0.75,
              "role": "pivot"
            },
            {
              "id": "F",
              "label": "F ∞+3",
              "x": 0.74,
              "y": 0.3
            },
            {
              "id": "G",
              "label": "G ∞+0",
              "x": 0.94,
              "y": 0.5
            }
          ],
          "edges": [
            {
              "from": "S",
              "to": "A",
              "weight": 3,
              "role": "sorted"
            },
            {
              "from": "S",
              "to": "B",
              "weight": 2,
              "role": "sorted"
            },
            {
              "from": "A",
              "to": "D",
              "weight": 4,
              "role": "compare"
            },
            {
              "from": "A",
              "to": "C",
              "weight": 3
            },
            {
              "from": "B",
              "to": "C",
              "weight": 4,
              "role": "sorted"
            },
            {
              "from": "B",
              "to": "E",
              "weight": 6,
              "role": "sorted"
            },
            {
              "from": "C",
              "to": "F",
              "weight": 3
            },
            {
              "from": "D",
              "to": "F",
              "weight": 5
            },
            {
              "from": "E",
              "to": "G",
              "weight": 4
            },
            {
              "from": "F",
              "to": "G",
              "weight": 2
            }
          ],
          "directed": false,
          "frontier": {
            "label": "queue",
            "ids": [
              "C",
              "E"
            ]
          },
          "visited": [
            "S",
            "B",
            "A"
          ]
        },
        "pointers": [],
        "highlights": [],
        "codeLine": 16,
        "variables": {
          "from": "A",
          "to": "D",
          "edge": 4,
          "via": 7,
          "known": "∞",
          "h": 6
        },
        "explanation": "A → D costs 3 + 4 = 7, better than the ∞ we had. Update g(D) = 7, so f(D) = 7 + 6 = 13.",
        "stats": {
          "comparisons": 8,
          "swaps": 4
        },
        "accent": "found"
      },
      {
        "data": {
          "nodes": [
            {
              "id": "S",
              "label": "S 0+9",
              "x": 0.08,
              "y": 0.5,
              "role": "sorted"
            },
            {
              "id": "A",
              "label": "A 3+7",
              "x": 0.3,
              "y": 0.18,
              "role": "sorted"
            },
            {
              "id": "B",
              "label": "B 2+7",
              "x": 0.3,
              "y": 0.82,
              "role": "sorted"
            },
            {
              "id": "C",
              "label": "C 6+4",
              "x": 0.52,
              "y": 0.5,
              "role": "compare"
            },
            {
              "id": "D",
              "label": "D 7+6",
              "x": 0.52,
              "y": 0.1,
              "role": "pivot"
            },
            {
              "id": "E",
              "label": "E 8+3",
              "x": 0.74,
              "y": 0.75,
              "role": "pivot"
            },
            {
              "id": "F",
              "label": "F ∞+3",
              "x": 0.74,
              "y": 0.3
            },
            {
              "id": "G",
              "label": "G ∞+0",
              "x": 0.94,
              "y": 0.5
            }
          ],
          "edges": [
            {
              "from": "S",
              "to": "A",
              "weight": 3,
              "role": "sorted"
            },
            {
              "from": "S",
              "to": "B",
              "weight": 2,
              "role": "sorted"
            },
            {
              "from": "A",
              "to": "D",
              "weight": 4,
              "role": "sorted"
            },
            {
              "from": "A",
              "to": "C",
              "weight": 3,
              "role": "compare"
            },
            {
              "from": "B",
              "to": "C",
              "weight": 4,
              "role": "sorted"
            },
            {
              "from": "B",
              "to": "E",
              "weight": 6,
              "role": "sorted"
            },
            {
              "from": "C",
              "to": "F",
              "weight": 3
            },
            {
              "from": "D",
              "to": "F",
              "weight": 5
            },
            {
              "from": "E",
              "to": "G",
              "weight": 4
            },
            {
              "from": "F",
              "to": "G",
              "weight": 2
            }
          ],
          "directed": false,
          "frontier": {
            "label": "queue",
            "ids": [
              "C",
              "E",
              "D"
            ]
          },
          "visited": [
            "S",
            "B",
            "A"
          ]
        },
        "pointers": [],
        "highlights": [],
        "codeLine": 16,
        "variables": {
          "from": "A",
          "to": "C",
          "edge": 3,
          "via": 6,
          "known": "6",
          "h": 4
        },
        "explanation": "A → C costs 6, no better than the 6 we know. Skip.",
        "stats": {
          "comparisons": 9,
          "swaps": 5
        },
        "accent": "compare"
      },
      {
        "data": {
          "nodes": [
            {
              "id": "S",
              "label": "S 0+9",
              "x": 0.08,
              "y": 0.5,
              "role": "sorted"
            },
            {
              "id": "A",
              "label": "A 3+7",
              "x": 0.3,
              "y": 0.18,
              "role": "sorted"
            },
            {
              "id": "B",
              "label": "B 2+7",
              "x": 0.3,
              "y": 0.82,
              "role": "sorted"
            },
            {
              "id": "C",
              "label": "C 6+4",
              "x": 0.52,
              "y": 0.5,
              "role": "sorted"
            },
            {
              "id": "D",
              "label": "D 7+6",
              "x": 0.52,
              "y": 0.1,
              "role": "pivot"
            },
            {
              "id": "E",
              "label": "E 8+3",
              "x": 0.74,
              "y": 0.75,
              "role": "pivot"
            },
            {
              "id": "F",
              "label": "F ∞+3",
              "x": 0.74,
              "y": 0.3
            },
            {
              "id": "G",
              "label": "G ∞+0",
              "x": 0.94,
              "y": 0.5
            }
          ],
          "edges": [
            {
              "from": "S",
              "to": "A",
              "weight": 3,
              "role": "sorted"
            },
            {
              "from": "S",
              "to": "B",
              "weight": 2,
              "role": "sorted"
            },
            {
              "from": "A",
              "to": "D",
              "weight": 4,
              "role": "sorted"
            },
            {
              "from": "A",
              "to": "C",
              "weight": 3
            },
            {
              "from": "B",
              "to": "C",
              "weight": 4,
              "role": "sorted"
            },
            {
              "from": "B",
              "to": "E",
              "weight": 6,
              "role": "sorted"
            },
            {
              "from": "C",
              "to": "F",
              "weight": 3
            },
            {
              "from": "D",
              "to": "F",
              "weight": 5
            },
            {
              "from": "E",
              "to": "G",
              "weight": 4
            },
            {
              "from": "F",
              "to": "G",
              "weight": 2
            }
          ],
          "directed": false,
          "frontier": {
            "label": "queue",
            "ids": [
              "E",
              "D"
            ]
          },
          "visited": [
            "S",
            "B",
            "A",
            "C"
          ]
        },
        "pointers": [],
        "highlights": [],
        "codeLine": 12,
        "variables": {
          "expanding": "C",
          "g": "6",
          "h": 4,
          "f": 10
        },
        "explanation": "Expand C: it has the lowest f = g + h = 6 + 4 = 10. Dijkstra would have picked purely on g and might have gone the wrong way; the h term is what makes A* aim.",
        "stats": {
          "comparisons": 10,
          "swaps": 5
        },
        "accent": "sorted"
      },
      {
        "data": {
          "nodes": [
            {
              "id": "S",
              "label": "S 0+9",
              "x": 0.08,
              "y": 0.5,
              "role": "sorted"
            },
            {
              "id": "A",
              "label": "A 3+7",
              "x": 0.3,
              "y": 0.18,
              "role": "sorted"
            },
            {
              "id": "B",
              "label": "B 2+7",
              "x": 0.3,
              "y": 0.82,
              "role": "sorted"
            },
            {
              "id": "C",
              "label": "C 6+4",
              "x": 0.52,
              "y": 0.5,
              "role": "sorted"
            },
            {
              "id": "D",
              "label": "D 7+6",
              "x": 0.52,
              "y": 0.1,
              "role": "pivot"
            },
            {
              "id": "E",
              "label": "E 8+3",
              "x": 0.74,
              "y": 0.75,
              "role": "pivot"
            },
            {
              "id": "F",
              "label": "F ∞+3",
              "x": 0.74,
              "y": 0.3,
              "role": "compare"
            },
            {
              "id": "G",
              "label": "G ∞+0",
              "x": 0.94,
              "y": 0.5
            }
          ],
          "edges": [
            {
              "from": "S",
              "to": "A",
              "weight": 3,
              "role": "sorted"
            },
            {
              "from": "S",
              "to": "B",
              "weight": 2,
              "role": "sorted"
            },
            {
              "from": "A",
              "to": "D",
              "weight": 4,
              "role": "sorted"
            },
            {
              "from": "A",
              "to": "C",
              "weight": 3
            },
            {
              "from": "B",
              "to": "C",
              "weight": 4,
              "role": "sorted"
            },
            {
              "from": "B",
              "to": "E",
              "weight": 6,
              "role": "sorted"
            },
            {
              "from": "C",
              "to": "F",
              "weight": 3,
              "role": "compare"
            },
            {
              "from": "D",
              "to": "F",
              "weight": 5
            },
            {
              "from": "E",
              "to": "G",
              "weight": 4
            },
            {
              "from": "F",
              "to": "G",
              "weight": 2
            }
          ],
          "directed": false,
          "frontier": {
            "label": "queue",
            "ids": [
              "E",
              "D"
            ]
          },
          "visited": [
            "S",
            "B",
            "A",
            "C"
          ]
        },
        "pointers": [],
        "highlights": [],
        "codeLine": 16,
        "variables": {
          "from": "C",
          "to": "F",
          "edge": 3,
          "via": 9,
          "known": "∞",
          "h": 3
        },
        "explanation": "C → F costs 6 + 3 = 9, better than the ∞ we had. Update g(F) = 9, so f(F) = 9 + 3 = 12.",
        "stats": {
          "comparisons": 11,
          "swaps": 5
        },
        "accent": "found"
      },
      {
        "data": {
          "nodes": [
            {
              "id": "S",
              "label": "S 0+9",
              "x": 0.08,
              "y": 0.5,
              "role": "sorted"
            },
            {
              "id": "A",
              "label": "A 3+7",
              "x": 0.3,
              "y": 0.18,
              "role": "sorted"
            },
            {
              "id": "B",
              "label": "B 2+7",
              "x": 0.3,
              "y": 0.82,
              "role": "sorted"
            },
            {
              "id": "C",
              "label": "C 6+4",
              "x": 0.52,
              "y": 0.5,
              "role": "sorted"
            },
            {
              "id": "D",
              "label": "D 7+6",
              "x": 0.52,
              "y": 0.1,
              "role": "pivot"
            },
            {
              "id": "E",
              "label": "E 8+3",
              "x": 0.74,
              "y": 0.75,
              "role": "sorted"
            },
            {
              "id": "F",
              "label": "F 9+3",
              "x": 0.74,
              "y": 0.3,
              "role": "pivot"
            },
            {
              "id": "G",
              "label": "G ∞+0",
              "x": 0.94,
              "y": 0.5
            }
          ],
          "edges": [
            {
              "from": "S",
              "to": "A",
              "weight": 3,
              "role": "sorted"
            },
            {
              "from": "S",
              "to": "B",
              "weight": 2,
              "role": "sorted"
            },
            {
              "from": "A",
              "to": "D",
              "weight": 4,
              "role": "sorted"
            },
            {
              "from": "A",
              "to": "C",
              "weight": 3
            },
            {
              "from": "B",
              "to": "C",
              "weight": 4,
              "role": "sorted"
            },
            {
              "from": "B",
              "to": "E",
              "weight": 6,
              "role": "sorted"
            },
            {
              "from": "C",
              "to": "F",
              "weight": 3,
              "role": "sorted"
            },
            {
              "from": "D",
              "to": "F",
              "weight": 5
            },
            {
              "from": "E",
              "to": "G",
              "weight": 4
            },
            {
              "from": "F",
              "to": "G",
              "weight": 2
            }
          ],
          "directed": false,
          "frontier": {
            "label": "queue",
            "ids": [
              "D",
              "F"
            ]
          },
          "visited": [
            "S",
            "B",
            "A",
            "C",
            "E"
          ]
        },
        "pointers": [],
        "highlights": [],
        "codeLine": 12,
        "variables": {
          "expanding": "E",
          "g": "8",
          "h": 3,
          "f": 11
        },
        "explanation": "Expand E: it has the lowest f = g + h = 8 + 3 = 11. Dijkstra would have picked purely on g and might have gone the wrong way; the h term is what makes A* aim.",
        "stats": {
          "comparisons": 12,
          "swaps": 6
        },
        "accent": "sorted"
      },
      {
        "data": {
          "nodes": [
            {
              "id": "S",
              "label": "S 0+9",
              "x": 0.08,
              "y": 0.5,
              "role": "sorted"
            },
            {
              "id": "A",
              "label": "A 3+7",
              "x": 0.3,
              "y": 0.18,
              "role": "sorted"
            },
            {
              "id": "B",
              "label": "B 2+7",
              "x": 0.3,
              "y": 0.82,
              "role": "sorted"
            },
            {
              "id": "C",
              "label": "C 6+4",
              "x": 0.52,
              "y": 0.5,
              "role": "sorted"
            },
            {
              "id": "D",
              "label": "D 7+6",
              "x": 0.52,
              "y": 0.1,
              "role": "pivot"
            },
            {
              "id": "E",
              "label": "E 8+3",
              "x": 0.74,
              "y": 0.75,
              "role": "sorted"
            },
            {
              "id": "F",
              "label": "F 9+3",
              "x": 0.74,
              "y": 0.3,
              "role": "pivot"
            },
            {
              "id": "G",
              "label": "G ∞+0",
              "x": 0.94,
              "y": 0.5,
              "role": "compare"
            }
          ],
          "edges": [
            {
              "from": "S",
              "to": "A",
              "weight": 3,
              "role": "sorted"
            },
            {
              "from": "S",
              "to": "B",
              "weight": 2,
              "role": "sorted"
            },
            {
              "from": "A",
              "to": "D",
              "weight": 4,
              "role": "sorted"
            },
            {
              "from": "A",
              "to": "C",
              "weight": 3
            },
            {
              "from": "B",
              "to": "C",
              "weight": 4,
              "role": "sorted"
            },
            {
              "from": "B",
              "to": "E",
              "weight": 6,
              "role": "sorted"
            },
            {
              "from": "C",
              "to": "F",
              "weight": 3,
              "role": "sorted"
            },
            {
              "from": "D",
              "to": "F",
              "weight": 5
            },
            {
              "from": "E",
              "to": "G",
              "weight": 4,
              "role": "compare"
            },
            {
              "from": "F",
              "to": "G",
              "weight": 2
            }
          ],
          "directed": false,
          "frontier": {
            "label": "queue",
            "ids": [
              "D",
              "F"
            ]
          },
          "visited": [
            "S",
            "B",
            "A",
            "C",
            "E"
          ]
        },
        "pointers": [],
        "highlights": [],
        "codeLine": 16,
        "variables": {
          "from": "E",
          "to": "G",
          "edge": 4,
          "via": 12,
          "known": "∞",
          "h": 0
        },
        "explanation": "E → G costs 8 + 4 = 12, better than the ∞ we had. Update g(G) = 12, so f(G) = 12 + 0 = 12.",
        "stats": {
          "comparisons": 13,
          "swaps": 6
        },
        "accent": "found"
      },
      {
        "data": {
          "nodes": [
            {
              "id": "S",
              "label": "S 0+9",
              "x": 0.08,
              "y": 0.5,
              "role": "sorted"
            },
            {
              "id": "A",
              "label": "A 3+7",
              "x": 0.3,
              "y": 0.18,
              "role": "sorted"
            },
            {
              "id": "B",
              "label": "B 2+7",
              "x": 0.3,
              "y": 0.82,
              "role": "sorted"
            },
            {
              "id": "C",
              "label": "C 6+4",
              "x": 0.52,
              "y": 0.5,
              "role": "sorted"
            },
            {
              "id": "D",
              "label": "D 7+6",
              "x": 0.52,
              "y": 0.1,
              "role": "pivot"
            },
            {
              "id": "E",
              "label": "E 8+3",
              "x": 0.74,
              "y": 0.75,
              "role": "sorted"
            },
            {
              "id": "F",
              "label": "F 9+3",
              "x": 0.74,
              "y": 0.3,
              "role": "sorted"
            },
            {
              "id": "G",
              "label": "G 12+0",
              "x": 0.94,
              "y": 0.5,
              "role": "pivot"
            }
          ],
          "edges": [
            {
              "from": "S",
              "to": "A",
              "weight": 3,
              "role": "sorted"
            },
            {
              "from": "S",
              "to": "B",
              "weight": 2,
              "role": "sorted"
            },
            {
              "from": "A",
              "to": "D",
              "weight": 4,
              "role": "sorted"
            },
            {
              "from": "A",
              "to": "C",
              "weight": 3
            },
            {
              "from": "B",
              "to": "C",
              "weight": 4,
              "role": "sorted"
            },
            {
              "from": "B",
              "to": "E",
              "weight": 6,
              "role": "sorted"
            },
            {
              "from": "C",
              "to": "F",
              "weight": 3,
              "role": "sorted"
            },
            {
              "from": "D",
              "to": "F",
              "weight": 5
            },
            {
              "from": "E",
              "to": "G",
              "weight": 4,
              "role": "sorted"
            },
            {
              "from": "F",
              "to": "G",
              "weight": 2
            }
          ],
          "directed": false,
          "frontier": {
            "label": "queue",
            "ids": [
              "D",
              "G"
            ]
          },
          "visited": [
            "S",
            "B",
            "A",
            "C",
            "E",
            "F"
          ]
        },
        "pointers": [],
        "highlights": [],
        "codeLine": 12,
        "variables": {
          "expanding": "F",
          "g": "9",
          "h": 3,
          "f": 12
        },
        "explanation": "Expand F: it has the lowest f = g + h = 9 + 3 = 12. Dijkstra would have picked purely on g and might have gone the wrong way; the h term is what makes A* aim.",
        "stats": {
          "comparisons": 14,
          "swaps": 7
        },
        "accent": "sorted"
      },
      {
        "data": {
          "nodes": [
            {
              "id": "S",
              "label": "S 0+9",
              "x": 0.08,
              "y": 0.5,
              "role": "sorted"
            },
            {
              "id": "A",
              "label": "A 3+7",
              "x": 0.3,
              "y": 0.18,
              "role": "sorted"
            },
            {
              "id": "B",
              "label": "B 2+7",
              "x": 0.3,
              "y": 0.82,
              "role": "sorted"
            },
            {
              "id": "C",
              "label": "C 6+4",
              "x": 0.52,
              "y": 0.5,
              "role": "sorted"
            },
            {
              "id": "D",
              "label": "D 7+6",
              "x": 0.52,
              "y": 0.1,
              "role": "compare"
            },
            {
              "id": "E",
              "label": "E 8+3",
              "x": 0.74,
              "y": 0.75,
              "role": "sorted"
            },
            {
              "id": "F",
              "label": "F 9+3",
              "x": 0.74,
              "y": 0.3,
              "role": "sorted"
            },
            {
              "id": "G",
              "label": "G 12+0",
              "x": 0.94,
              "y": 0.5,
              "role": "pivot"
            }
          ],
          "edges": [
            {
              "from": "S",
              "to": "A",
              "weight": 3,
              "role": "sorted"
            },
            {
              "from": "S",
              "to": "B",
              "weight": 2,
              "role": "sorted"
            },
            {
              "from": "A",
              "to": "D",
              "weight": 4,
              "role": "sorted"
            },
            {
              "from": "A",
              "to": "C",
              "weight": 3
            },
            {
              "from": "B",
              "to": "C",
              "weight": 4,
              "role": "sorted"
            },
            {
              "from": "B",
              "to": "E",
              "weight": 6,
              "role": "sorted"
            },
            {
              "from": "C",
              "to": "F",
              "weight": 3,
              "role": "sorted"
            },
            {
              "from": "D",
              "to": "F",
              "weight": 5,
              "role": "compare"
            },
            {
              "from": "E",
              "to": "G",
              "weight": 4,
              "role": "sorted"
            },
            {
              "from": "F",
              "to": "G",
              "weight": 2
            }
          ],
          "directed": false,
          "frontier": {
            "label": "queue",
            "ids": [
              "D",
              "G"
            ]
          },
          "visited": [
            "S",
            "B",
            "A",
            "C",
            "E",
            "F"
          ]
        },
        "pointers": [],
        "highlights": [],
        "codeLine": 16,
        "variables": {
          "from": "F",
          "to": "D",
          "edge": 5,
          "via": 14,
          "known": "7",
          "h": 6
        },
        "explanation": "F → D costs 14, no better than the 7 we know. Skip.",
        "stats": {
          "comparisons": 15,
          "swaps": 7
        },
        "accent": "compare"
      },
      {
        "data": {
          "nodes": [
            {
              "id": "S",
              "label": "S 0+9",
              "x": 0.08,
              "y": 0.5,
              "role": "sorted"
            },
            {
              "id": "A",
              "label": "A 3+7",
              "x": 0.3,
              "y": 0.18,
              "role": "sorted"
            },
            {
              "id": "B",
              "label": "B 2+7",
              "x": 0.3,
              "y": 0.82,
              "role": "sorted"
            },
            {
              "id": "C",
              "label": "C 6+4",
              "x": 0.52,
              "y": 0.5,
              "role": "sorted"
            },
            {
              "id": "D",
              "label": "D 7+6",
              "x": 0.52,
              "y": 0.1,
              "role": "pivot"
            },
            {
              "id": "E",
              "label": "E 8+3",
              "x": 0.74,
              "y": 0.75,
              "role": "sorted"
            },
            {
              "id": "F",
              "label": "F 9+3",
              "x": 0.74,
              "y": 0.3,
              "role": "sorted"
            },
            {
              "id": "G",
              "label": "G 12+0",
              "x": 0.94,
              "y": 0.5,
              "role": "compare"
            }
          ],
          "edges": [
            {
              "from": "S",
              "to": "A",
              "weight": 3,
              "role": "sorted"
            },
            {
              "from": "S",
              "to": "B",
              "weight": 2,
              "role": "sorted"
            },
            {
              "from": "A",
              "to": "D",
              "weight": 4,
              "role": "sorted"
            },
            {
              "from": "A",
              "to": "C",
              "weight": 3
            },
            {
              "from": "B",
              "to": "C",
              "weight": 4,
              "role": "sorted"
            },
            {
              "from": "B",
              "to": "E",
              "weight": 6,
              "role": "sorted"
            },
            {
              "from": "C",
              "to": "F",
              "weight": 3,
              "role": "sorted"
            },
            {
              "from": "D",
              "to": "F",
              "weight": 5
            },
            {
              "from": "E",
              "to": "G",
              "weight": 4,
              "role": "sorted"
            },
            {
              "from": "F",
              "to": "G",
              "weight": 2,
              "role": "compare"
            }
          ],
          "directed": false,
          "frontier": {
            "label": "queue",
            "ids": [
              "D",
              "G"
            ]
          },
          "visited": [
            "S",
            "B",
            "A",
            "C",
            "E",
            "F"
          ]
        },
        "pointers": [],
        "highlights": [],
        "codeLine": 16,
        "variables": {
          "from": "F",
          "to": "G",
          "edge": 2,
          "via": 11,
          "known": "12",
          "h": 0
        },
        "explanation": "F → G costs 9 + 2 = 11, better than the 12 we had. Update g(G) = 11, so f(G) = 11 + 0 = 11.",
        "stats": {
          "comparisons": 16,
          "swaps": 7
        },
        "accent": "found"
      },
      {
        "data": {
          "nodes": [
            {
              "id": "S",
              "label": "S 0+9",
              "x": 0.08,
              "y": 0.5,
              "role": "sorted"
            },
            {
              "id": "A",
              "label": "A 3+7",
              "x": 0.3,
              "y": 0.18,
              "role": "sorted"
            },
            {
              "id": "B",
              "label": "B 2+7",
              "x": 0.3,
              "y": 0.82,
              "role": "sorted"
            },
            {
              "id": "C",
              "label": "C 6+4",
              "x": 0.52,
              "y": 0.5,
              "role": "sorted"
            },
            {
              "id": "D",
              "label": "D 7+6",
              "x": 0.52,
              "y": 0.1,
              "role": "pivot"
            },
            {
              "id": "E",
              "label": "E 8+3",
              "x": 0.74,
              "y": 0.75,
              "role": "sorted"
            },
            {
              "id": "F",
              "label": "F 9+3",
              "x": 0.74,
              "y": 0.3,
              "role": "sorted"
            },
            {
              "id": "G",
              "label": "G 11+0",
              "x": 0.94,
              "y": 0.5,
              "role": "sorted"
            }
          ],
          "edges": [
            {
              "from": "S",
              "to": "A",
              "weight": 3,
              "role": "sorted"
            },
            {
              "from": "S",
              "to": "B",
              "weight": 2,
              "role": "sorted"
            },
            {
              "from": "A",
              "to": "D",
              "weight": 4,
              "role": "sorted"
            },
            {
              "from": "A",
              "to": "C",
              "weight": 3
            },
            {
              "from": "B",
              "to": "C",
              "weight": 4,
              "role": "sorted"
            },
            {
              "from": "B",
              "to": "E",
              "weight": 6,
              "role": "sorted"
            },
            {
              "from": "C",
              "to": "F",
              "weight": 3,
              "role": "sorted"
            },
            {
              "from": "D",
              "to": "F",
              "weight": 5
            },
            {
              "from": "E",
              "to": "G",
              "weight": 4,
              "role": "sorted"
            },
            {
              "from": "F",
              "to": "G",
              "weight": 2,
              "role": "sorted"
            }
          ],
          "directed": false,
          "frontier": {
            "label": "queue",
            "ids": [
              "D"
            ]
          },
          "visited": [
            "S",
            "B",
            "A",
            "C",
            "E",
            "F",
            "G"
          ]
        },
        "pointers": [],
        "highlights": [],
        "codeLine": 13,
        "variables": {
          "reached": "G",
          "cost": 11,
          "expanded": 7
        },
        "explanation": "Reached G, at a true cost of 11. A* expanded only 7 of 8 nodes — the guess kept it pointed at the goal, so it never wandered off exploring the far side of the map.",
        "stats": {
          "comparisons": 17,
          "swaps": 8
        },
        "accent": "found"
      },
      {
        "data": {
          "nodes": [
            {
              "id": "S",
              "label": "S 0+9",
              "x": 0.08,
              "y": 0.5,
              "role": "sorted"
            },
            {
              "id": "A",
              "label": "A 3+7",
              "x": 0.3,
              "y": 0.18,
              "role": "sorted"
            },
            {
              "id": "B",
              "label": "B 2+7",
              "x": 0.3,
              "y": 0.82,
              "role": "sorted"
            },
            {
              "id": "C",
              "label": "C 6+4",
              "x": 0.52,
              "y": 0.5,
              "role": "sorted"
            },
            {
              "id": "D",
              "label": "D 7+6",
              "x": 0.52,
              "y": 0.1,
              "role": "pivot"
            },
            {
              "id": "E",
              "label": "E 8+3",
              "x": 0.74,
              "y": 0.75,
              "role": "sorted"
            },
            {
              "id": "F",
              "label": "F 9+3",
              "x": 0.74,
              "y": 0.3,
              "role": "sorted"
            },
            {
              "id": "G",
              "label": "G 11+0",
              "x": 0.94,
              "y": 0.5,
              "role": "sorted"
            }
          ],
          "edges": [
            {
              "from": "S",
              "to": "A",
              "weight": 3,
              "role": "sorted"
            },
            {
              "from": "S",
              "to": "B",
              "weight": 2,
              "role": "sorted"
            },
            {
              "from": "A",
              "to": "D",
              "weight": 4,
              "role": "sorted"
            },
            {
              "from": "A",
              "to": "C",
              "weight": 3
            },
            {
              "from": "B",
              "to": "C",
              "weight": 4,
              "role": "sorted"
            },
            {
              "from": "B",
              "to": "E",
              "weight": 6,
              "role": "sorted"
            },
            {
              "from": "C",
              "to": "F",
              "weight": 3,
              "role": "sorted"
            },
            {
              "from": "D",
              "to": "F",
              "weight": 5
            },
            {
              "from": "E",
              "to": "G",
              "weight": 4,
              "role": "sorted"
            },
            {
              "from": "F",
              "to": "G",
              "weight": 2,
              "role": "sorted"
            }
          ],
          "directed": false,
          "frontier": {
            "label": "queue",
            "ids": [
              "D"
            ]
          },
          "visited": [
            "S",
            "B",
            "A",
            "C",
            "E",
            "F",
            "G"
          ]
        },
        "pointers": [],
        "highlights": [],
        "codeLine": 20,
        "variables": {
          "cost": "11",
          "expanded": 7,
          "neverTouched": "D"
        },
        "explanation": "Cheapest route to G: 11. It never even looked at D — the heuristic said they were pointing away from the goal. With h set to 0, A* *is* Dijkstra. The whole difference is the guess — and it only stays correct while that guess never overestimates.",
        "stats": {
          "comparisons": 17,
          "swaps": 8
        },
        "accent": "sorted"
      }
    ]
  }
}