2477. Minimum Fuel Cost to Report to the Capital - Explanation

Problem Link

Description

The bidirectional roads in roads connect n = roads.length + 1 cities into a tree. Cities are labeled 0 through n - 1, and city 0 is the capital.

Each city has one representative and one car. Every car has seats seats, and each car uses one liter of fuel whenever it crosses a road. Representatives may share cars and transfer between cars at a city.

Return the minimum total fuel needed to bring all representatives to city 0. The representative already in the capital does not need to travel.

Example 1:

Minimum Fuel Cost to Report to the Capital, example 1: illustration of the example

Input: roads = [[0,1],[1,2],[2,3]]
seats = 2

Output: 4

Explanation: The representative from city 3 uses 1 liter to reach city 2. Those two representatives share a car to city 1 for 1 more liter. The three representatives now need two cars to cross from city 1 to city 0, costing 2 more liters. Total: 4.

Example 2:

Minimum Fuel Cost to Report to the Capital, example 2: illustration of the example

Input: roads = [[0,1],[0,2],[0,3]]
seats = 4

Output: 3

Explanation: Each noncapital city has its own road to city 0. Its representative must cross that road once, so three car trips cost 3 liters in total.

Example 3:

Minimum Fuel Cost to Report to the Capital, example 3: illustration of the example

Input: roads = []
seats = 3

Output: 0

Explanation: There is only city 0. Its representative is already at the meeting, so no fuel is needed.

Constraints:

  • n == roads.length + 1
  • 1 <= n <= 100000
  • roads[i].length == 2
  • Each road joins two distinct city labels between 0 and n - 1.
  • The roads form a connected tree.
  • 1 <= seats <= 100000


Topics

Company Tags

Please upgrade to NeetCode Pro to view company tags.



Prerequisites

Before attempting this problem, you should be comfortable with:

  • Tree/Graph Representation - Understanding how to represent trees using adjacency lists and traversing undirected graphs
  • Depth First Search (DFS) - Ability to traverse trees recursively while tracking parent nodes to avoid revisiting
  • Ceiling Division - Knowing how to compute the ceiling of integer division (e.g., using (a + b - 1) / b or math.ceil)

Intuition

Think of the tree as a network of cities where everyone needs to travel to the capital (node 0). Since the tree structure means there's only one path from any city to the capital, we can work backwards from the leaves.

The key insight is that as we move toward the capital, passengers accumulate. At each node, we collect all the people from its subtree, and the number of cars needed to transport them equals the ceiling of passengers divided by seats. By using dfs to traverse from leaves to the root, we can count passengers bottom-up and calculate fuel costs as people flow toward the capital.

Algorithm

  1. Build an adjacency list from the given roads.
  2. Run dfs starting from node 0, tracking the parent to avoid revisiting.
  3. For each node, recursively gather passengers from all child subtrees.
  4. After processing children, add the fuel cost for moving those passengers one edge closer to the capital: ceil(passengers / seats).
  5. Return total passengers from the subtree (including the current node's representative).
  6. The accumulated fuel cost across all edges gives the answer.
class Solution:
    def minimumFuelCost(self, roads: list[list[int]], seats: int) -> int:
        adj = defaultdict(list)
        for src, dst in roads:
            adj[src].append(dst)
            adj[dst].append(src)

        res = 0
        def dfs(node, parent):
            nonlocal res
            passengers = 0
            for child in adj[node]:
                if child != parent:
                    p = dfs(child, node)
                    passengers += p
                    res += ceil(p / seats)
            return passengers + 1

        dfs(0, -1)
        return res

Time & Space Complexity

  • Time complexity: O(n)O(n)
  • Space complexity: O(n)O(n)

2. Topological Sort (Kahn's Algorithm)

Intuition

Instead of recursion, we can process the tree level by level starting from the leaf nodes. Leaves have only one connection, so we identify them by their degree. As each leaf "sends" its passengers toward the capital, we remove it from consideration and check if its neighbor becomes a new leaf.

This approach simulates the natural flow of people gathering and moving inward. Each time a node is processed, we calculate how many cars are needed to transport its passengers one step closer to the root.

Algorithm

  1. Build an adjacency list and track the degree (number of edges) for each node.
  2. Initialize a passengers array where each node starts with 1 (itself).
  3. Add all nodes with degree 1 (except node 0) to the queue as initial leaves.
  4. Process the queue: for each leaf, add ceil(passengers / seats) to the total fuel.
  5. Transfer the leaf's passengers to its neighbor and decrement the neighbor's degree.
  6. If the neighbor becomes a leaf (degree 1) and is not the capital, add it to the queue.
  7. Return the total fuel cost.
class Solution:
    def minimumFuelCost(self, roads: list[list[int]], seats: int) -> int:
        n = len(roads) + 1
        adj = [[] for _ in range(n)]
        indegree = [0] * n
        passengers = [1] * n
        res = 0

        for src, dst in roads:
            adj[src].append(dst)
            adj[dst].append(src)
            indegree[src] += 1
            indegree[dst] += 1

        q = deque()
        for i in range(1, n):
            if indegree[i] == 1:
                q.append(i)

        while q:
            node = q.popleft()
            res += math.ceil(passengers[node] / seats)
            for parent in adj[node]:
                indegree[parent] -= 1
                if indegree[parent] == 1 and parent != 0:
                    q.append(parent)
                passengers[parent] += passengers[node]

        return res

Time & Space Complexity

  • Time complexity: O(n)O(n)
  • Space complexity: O(n)O(n)

Common Pitfalls

Counting Fuel for the Capital Node

The capital (node 0) does not need to travel anywhere, so you should not add fuel cost for passengers arriving at node 0. A common mistake is calculating ceil(passengers / seats) for the capital itself, which incorrectly inflates the total fuel cost.

Incorrect Ceiling Division

When calculating cars needed, you need ceil(passengers / seats). Integer division truncates, so 7 / 3 = 2 instead of the correct 3. Use (passengers + seats - 1) / seats or a ceiling function to get the correct result. Floating-point division with casting can also introduce precision errors.

Revisiting the Parent in DFS

Since the graph is undirected, the adjacency list includes edges in both directions. When traversing with DFS, you must skip the parent node to avoid infinite recursion. Forgetting to pass and check the parent parameter causes stack overflow or incorrect passenger counts.