Підлеглі#11429

Підлеглі (Розбір)

Структура компанії є деревом. Для кожної вершини дерева необхідно визначити кількість вершин в піддереві, де вона є коренем. Тоді кількість підлеглих у співробітника буде дорівнювати sum[v] - 1 (оскільки співробітник не є власним підлеглим).

Запустимо пошук в глибину з вершини , яка відповідає генеральному директору компанії. Якщо to_1, to_2, ..., to_k — сини вершини , то

sum[v] = 1 + sum[to_1] + sum[to_2] + ... + sum[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=" ")