Структура компанії є деревом. Для кожної вершини дерева необхідно визначити кількість вершин в піддереві, де вона є коренем. Тоді кількість підлеглих у співробітника буде дорівнювати sum[v] - 1 (оскільки співробітник не є власним підлеглим).
Запустимо пошук в глибину з вершини , яка відповідає генеральному директору компанії. Якщо to_1, to_2, ..., to_k — сини вершини , то
Якщо вершина є листом дерева, то встановимо sum[v] = 1.
Приклад
Розглянемо приклад. Біля кожного співробітника (вершини графа) вказано кількість його підлеглих.
Реалізація алгоритму
Дерево зберігаємо в списку суміжності .
vector<vector<int> > g;Функція dfs виконує пошук в глибину з вершини і повертає кількість вершин в піддереві з коренем в . Вершина є предком при пошуку в глибину.
int dfs(int v, int p)
{Піддерево з коренем спочатку містить тільки одну вершину — вершину .
sum[v] = 1;Розглядаємо ребро v → to. Якщо to \ne p, то додаємо до кількість вершин в піддереві з коренем .
for (int to : g[v])
if (to != p) sum[v] += dfs(to, v);Повертаємо кількість вершин в піддереві з коренем .
return sum[v];
}Основна частина програми. Читаємо вхідні дані. Будуємо дерево.
scanf("%d", &n);
g.resize(n + 1);
for (i = 2; i <= n; i++)
{
scanf("%d", &x);Для співробітника безпосереднім начальником в компанії є .
g[i].push_back(x);
g[x].push_back(i);
}Запускаємо пошук в глибину з вершини .
sum.resize(n + 1);
dfs(1, -1);Виводимо відповідь. Кількість підлеглих співробітника дорівнює .
for (i = 1; i <= n; i++)
printf("%d ", sum[i] - 1);
printf("\n");Реалізація на Java
import java.util.*;
public class Main
{
static ArrayList<Integer>[] g;
static int sum[];
static int n;
static int dfs(int v, int p)
{
sum[v] = 1;
for(int to : g[v])
if (to != p) sum[v] += dfs(to,v);
return sum[v];
}
@SuppressWarnings("unchecked")
public static void main(String[] args)
{
Scanner con = new Scanner(System.in);
n = con.nextInt();
g = new ArrayList[n+1]; // unchecked
sum = new int[n+1];
for (int i = 0; i <= n; i++)
g[i] = new ArrayList<Integer>();
for (int i = 2; i <= n; i++)
{
int x = con.nextInt();
g[i].add(x);
g[x].add(i);
}
dfs(1,-1);
for (int i = 1; i <= n; i++)
System.out.print(sum[i] - 1 + " ");
System.out.println();
con.close();
}
} Реалізація на Python
Збільшимо стек для рекурсії.
import sys
sys.setrecursionlimit(1000000)Функція dfs виконує пошук в глибину з вершини і повертає кількість вершин в піддереві з коренем . Вершина є предком при пошуку в глибину.
def dfs(v, p):Піддерево з коренем спочатку містить тільки одну вершину — вершину .
sum[v] = 1Розглядаємо ребро v → to. Якщо to \ne p, то додаємо до кількість вершин в піддереві з коренем .
for to in g[v]:
if to != p: sum[v] += dfs(to,v)Повертаємо кількість вершин в піддереві з коренем .
return sum[v]Основна частина програми. Читаємо кількість співробітників .
n = int(input())Ініціалізуємо список суміжності графа .
g = [[] for _ in range(n+1)]Читаємо вхідні дані. Будуємо дерево.
lst = list(map(int, input().split()))
for i in range(2,n+1):
a = lst[i-2]Для співробітника i~(i \ge 2) безпосереднім начальником в компанії є .
g[a].append(i)
g[i].append(a)Ініціалізуємо список .
sum = [0] * (n + 1)Запускаємо пошук в глибину з вершини .
dfs(1,-1)Виводимо відповідь. Кількість підлеглих співробітника дорівнює sum[i] - 1.
for i in range(1, n+1):
print(sum[i] - 1,end=" ")