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:
If the stack s[color] is not empty, its top element contains the number of the vertex that is the nearest ancestor of vertex with the same color. If the stack is empty, such a vertex does not exist, and the answer for vertex should be .
Push vertex onto the stack s[color].
Recursively perform a depth-first search from all children of vertex .
After finishing the processing of vertex , remove it from the stack s[color].
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:])