This problem can be solved using Dynamic Programming on Trees, you can read about it here https://www.geeksforgeeks.org/dynamic-programming-trees-set-2/.
Let's split the problem into two parts, the first one is to find the number of paths that are valid in the subtree of a node u
. The second part is to find the answer for the node u
if we do not consider its subtree but going to it's parent and so on.
Let us consider 1 as the root of the tree.
Now for solving the first part, we will make an array in[]
in which we will store the
the number of paths in the subtree of node u
so in[u]
will represent the number of valid paths starting from the node u
and visiting its subtree. To compute this array we can run a simple dfs as follows :
//u is the current node - p is the parent
void dfs1(int u, int p) {
for (int i = 0; i < g[u].size(); i++) { //iterate through the adjacency of node u
int v = g[u][i]; // v is the child of u
if (v != p) { //in case v is the parent just ignore it
dfs1(v, u); //go to node v
if (u >= k && v >= k) { //if value of u or v is less than k then we cant start at this node so it should be 0
in[u] += in[v] + 1; //add to number of paths of u the number of paths starting from the node v + 1 (+1 because we can also go from u to v)
}
}
}
}
For solving the second part we need an array out[]
with out[u]
being the number of paths that are valid if we do not consider the subtree of u
which is going to the parent of u
and so on.
lets call the parent of u
P[u]
. To compute out[u]
we will rely on p[u]
. out[i]
is number of valid paths if we go to p[u]
, and what we can do once we reach p[u]
is either go through its subtree (excluding the brach of u
of course) or visit p[p[u]]
(the parent of parent of u
) so out[u]
is (out[p[u]] + 1) + (in[p[u]] - in[u] - 1)
.
// u is the current node - p is the parent
void dfs2(int u, int p) {
for (int i = 0; i < g[u].size(); i++) { // iterate through the adjacency of node u
int v = g[u][i]; // v is the child of u
if (v != p) { // in case v is the parent just ignore it
if (v >= k && u >= k) { // if value of u or v is less than k then we cant start at this node so it should be 0
out[v] += (out[u] + 1); //add to the number of paths of v the number of paths from it's parent (u) + 1 if we dont use the subtree of u
out[v] += (in[u] - in[v] - 1); // add to the number of paths of v the number of paths from it's parent (u)
// we should subtract in[v] + 1 because we want to exclude this branch from the subtree of the parent
}
dfs2(v, u); // go to node v
}
}
}
To find the answer just sum all out[u] + in[u]
for all the nodes and divide by 2 because each path was computed twice.
complexity O(V+E)