The Corporate Hierarchy Problem

January 9, 2026 • 6 min read

In systems engineering, we often deal with dependencies. Service A calls Service B, which calls Service C. In the corporate world, it’s an Org Chart.

The problem CSES 1674: Subordinates asks a deceptively simple question: Given a company structure, calculate how many subordinates each employee has.

Not just direct reports—everyone down the chain.

The Input

We are given $N$ employees ($2 \le N \le 200,000$). Employee 1 is the General Director (Root). For every other employee $i$, we are told who their direct boss is.

5          (Total employees)
1 1 2 3    (Bosses for employees 2, 3, 4, 5)

Step 1: Modeling the Data

The input gives us the data as a list of parents:

If we store it exactly like this (an array where parent[i] = boss), we have a problem. To find out who reports to Employee 1, we have to scan the entire array to check who lists “1” as their boss. This is inefficient.

The Right Structure: Adjacency List

We need to invert the relationship. Instead of “Who is my boss?”, we need to answer “Who is on my team?”.

We represent this as a Directed Graph (specifically a Tree) using an Adjacency List. adj[Boss] = [Employee A, Employee B, ...]

For our example:

Step 2: The Brute Force Trap

The naive instinct is to simulate the counting process for each person individually.

// Pseudocode for Brute Force
for each employee i from 1 to N:
    count = 0
    queue = [all direct reports of i]
    while queue is not empty:
        current = queue.pop()
        count++
        add current's reports to queue
    print count

Why this fails

Imagine the company is a straight line: 1 -> 2 -> 3 -> ... -> 200,000.

This is an Arithmetic Progression. The time complexity is $O(N^2)$. With $N = 200,000$, $N^2 = 40,000,000,000$ operations. This will timeout instantly.

Step 3: The Recursive “Leap of Faith”

We need an $O(N)$ solution. We need to touch every node exactly once.

Notice a pattern?

The formula is: \(Subordinates(X) = \sum_{child \in Children(X)} (1 + Subordinates(child))\)

This is where the Recursive Leap of Faith comes in. When writing the function get_subs(child), we don’t need to know how it calculates the answer. We just assume the contract holds: It will return the correct count.

The Algorithm (DFS Post-Order)

We use a Depth First Search.

  1. Dive to the bottom of the tree (leaf nodes).
  2. Leaf nodes return 0.
  3. Parents sum up the results of their children as the recursion unwinds.

The Solution

Here is the implementation.

import sys

# 1. Essential: Increase recursion depth
# The tree depth can be up to N (200,000), so we set a safe margin.
sys.setrecursionlimit(300000)

def solve():
    # 2. Fast I/O
    # Read all input at once into a list of strings
    input_data = sys.stdin.read().split()
    
    if not input_data:
        return

    # Use an iterator to consume the input tokens cleanly
    iterator = iter(input_data)
    n = int(next(iterator))
    
    # 3. Build Adjacency List
    # adj[boss] = [list of direct reports]
    # Using size n + 1 for 1-based indexing
    adj = [[] for _ in range(n + 1)]
    
    # The input contains n-1 integers representing bosses for employees 2..n
    for employee in range(2, n + 1):
        boss = int(next(iterator))
        adj[boss].append(employee)
        
    # Array to store the result for each employee
    subordinates = [0] * (n + 1)
    
    # 4. DFS Recursion
    def get_subs(emp):
        count = 0
        for child in adj[emp]:
            # The Logic: My subs = (Child + Child's subs) + Next Child...
            count += 1 + get_subs(child)
        
        subordinates[emp] = count
        return count

    # Start from the General Director (1)
    get_subs(1)
    
    # 5. Print Results (1 to n)
    # The * operator unpacks the list for space-separated printing
    print(*(subordinates[1:]))

if __name__ == '__main__':
    solve()

Alternative Approaches?

Could we do this without recursion?

  1. Iterative DFS: We could simulate the recursion stack manually. This is complex to implement because we need to process the node after visiting children (Post-order), requiring us to manage state carefully.
  2. Topological Sort / Reverse BFS: Since it’s a hierarchy, we could find the “leafs” (nodes with indegree 0 in the reversed graph) and work our way up layer by layer.

However, for Tree problems, simple Recursion is usually the cleanest implementation of the “Divide and Conquer” strategy.

Key Takeaways

  1. Data Structure Choice: An input list of Parent -> Child links is rarely useful. Always convert it to an Adjacency List Parent -> [Children] for traversal.
  2. Pass by Reference: In C++, passing a vector by value copies the whole array. Always use & in recursive functions to avoid TLE.
  3. Trust the Recursion: Don’t try to visualize 200,000 stack frames. Define the base case (leaf), define the recurrence relation, and trust the logic.