Mancunian And Colored Tree#3983

Let us consider a simplified version of the problem. Suppose all the vertices of the tree are painted the same color. We initialize an empty stack and perform a depth-first search starting from the root of the tree. When entering a vertex , push it onto the stack. When the processing of vertex is complete, remove the top element from the stack (which will be vertex itself). After the DFS is finished, the stack will once again be empty.

Question: What will be on the top of the stack at the moment we enter vertex , just before we push onto the stack?

Now let us move on to solving the original problem. We create stacks — one for each color (for example, using a vector of stacks). Initially, all stacks are empty. Perform a DFS starting from the root of the tree — vertex . The processing of a vertex , painted in color , includes the following steps:

During the depth-first search, when we are at vertex , the stacks contain information about the colors of all vertices along the unique path from the root to vertex . In particular, the stack s[color] stores the numbers of all vertices on this path that are colored with . These vertices are pushed onto the stack in the order they are visited during the DFS.

Example

When the depth-first search reaches vertex , two out of the c = 4 stacks will be empty (those corresponding to colors and ).

Stack number (for color ) will contain vertex , and stack number (for color ) will contain vertex . Since vertex has color , its nearest ancestor with the same color is at the top of stack number .

Therefore, the nearest ancestor of vertex with the same color is vertex .

Algorithm implementation

Declare the arrays.

vector<int> col, res;
vector<vector<int> > g;
vector<stack<int> > s;

The dfs function performs a depth-first search starting from vertex .

void dfs(int v)
{

Vertex has color .

  int color = col[v];

The number of the nearest ancestor of vertex with the same color is stored in .

  if(s[color].empty())
    res[v] = -1;
  else
    res[v] = s[color].top();

Push vertex onto the stack corresponding to its color.

  s[color].push(v);

Iterate over all children of vertex and recursively perform a depth-first search from each of them.

  for (int to : g[v])
    dfs(to);

After processing vertex is complete (i.e., upon exiting it), remove it from the stack corresponding to its color.

  s[color].pop();
}

The main part of the program. Read the input data. Construct a tree.

scanf("%d %d", &n, &c);
g.resize(n + 1);
for(i = 2; i <= n; i++)
{
  scanf("%d",&val);
  g[val].push_back(i);
}

Read the colors of the tree's vertices.

col.resize(n + 1);
for(i = 1; i <= n; i++)
  scanf("%d",&col[i]);

Start a depth first search from vertex .

s.resize(c + 1);
res.resize(n + 1);
dfs(1);

Print the answer.

for(i = 1; i <= n; i++)
  printf("%d ",res[i]);
printf("\n");

Python implementation

Increase the recursion stack size.

import sys
sys.setrecursionlimit(1000000)

The dfs function performs a depth-first search starting from vertex .

def dfs(v):

Vertex has color .

  color = col[v]

The number of the nearest ancestor of vertex with the same color is stored in .

  if not s[color]:
    res[v] = -1
  else:
    res[v] = s[color][-1]

Push vertex onto the stack corresponding to its color.

  s[color].append(v)

Iterate over all children of vertex and recursively perform a depth-first search from each of them.

  for to in g[v]:
    dfs(to)

After processing vertex is complete (i.e., upon exiting it), remove it from the stack corresponding to its color.

  s[color].pop()

The main part of the program. Read the input data. Construct a tree.

n, c = map(int, input().split())
lst = list(map(int, input().split()))
g = [[] for _ in range(n + 1)]
for i in range(2, n + 1):
  val = lst[i - 2]
  g[val].append(i)

Read the colors of the tree's vertices.

col = [0] * (n + 1)
col[1:] = list(map(int, input().split()))

Start a depth first search from vertex .

s = [[] for _ in range(c + 1)]
res = [0] * (n + 1)
dfs(1)

Print the answer.

print(*res[1:])