# Check if two nodes are on same path in a tree

Given a tree (not necessarily a binary tree) and a number of queries such that every query takes two nodes of tree as parameters. For every query pair, find if two nodes are on the same path from root to the bottom.

For example, consider the below tree, if given queries are (1, 5), (1, 6) and (2, 6), then answers should be true, true and false respectively.

Note that 1 and 5 lie on same root to leaf path, so do 1 and 6, but 2 and 6 are not on same root to leaf path.

It is obvious that Depth First Search technique is to be used to solve above problem, the main problem is how to respond to multiple queries fast. Here our graph is a tree which may have any number of children. Now DFS in a tree if started from root node proceeds in a depth search manner i.e. Suppose root has three children and those children have only one child with them so if DFS is started then it first visits the first child of root node then will go deep to the child of that node. The situation with a small tree can be shown as follows:

The order of visiting the nodes will be – 1 2 5 3 6 4 7 .

Thus other children nodes are visited later until completely one child is succesfully visited till depth. To simplify this if we assume that we have a watch in our hand and we start walking from root in DFS manner.

Intime – When we visit the node for the first time

Outtime- If we again visit the node later but there is no children unvisited we call it outtime,

*Note: Any node in its sub-tree will always have intime < its children (or children of children) because it is always visited first before children (due to DFS) and will have outtime > all nodes in its sub-tree because before noting the outtime it waits for all of its children to be marked visited.*

For any two nodes u, v if they are in same path then,

Intime[v] < Intime[u] and Outtime[v] > Outtime[u] OR Intime[u] < Intime[v] and Outtime[u ]> Outtime[v]

- If given pair of nodes follows any of the two conditions, then they are on the same root to leaf path.
- Else not on same path (If two nodes are on different paths it means that no one is in subtree of each other).

**Pseudo Code **

We use a global variable time which will be incremented as dfs for a node begins and will also be incremented after

DFS(v) increment timer Intime[v] = timer mark v as visited for all u that are children of v DFS(u) increment timer Outtime[v] = timer end

Time Complexity – O(n) for preprocessing and O(1) per query.

**Implementation:**

Below is implementation of above pseudo code.

## C++

`// C++ program to check if given pairs lie on same ` `// path or not. ` `#include<bits/stdc++.h> ` `using` `namespace` `std; ` `const` `int` `MAX = 100001; ` ` ` `// To keep track of visited vertices in DFS ` `bool` `visit[MAX] = {0}; ` ` ` `// To store start and end time of all vertices ` `// during DFS. ` `int` `intime[MAX]; ` `int` `outtime[MAX]; ` ` ` `// initially timer is zero ` `int` `timer = 0; ` ` ` `// Does DFS of given graph and fills arrays ` `// intime[] and outtime[]. These arrays are used ` `// to answer given queries. ` `void` `dfs(vector<` `int` `> graph[], ` `int` `v) ` `{ ` ` ` `visit[v] = ` `true` `; ` ` ` ` ` `// Increment the timer as you enter ` ` ` `// the recursion for v ` ` ` `++timer; ` ` ` ` ` `// Upgrade the in time for the vertex ` ` ` `intime[v] = timer; ` ` ` ` ` `vector<` `int` `>::iterator it = graph[v].begin(); ` ` ` `while` `(it != graph[v].end()) ` ` ` `{ ` ` ` `if` `(visit[*it]==` `false` `) ` ` ` `dfs(graph, *it); ` ` ` `it++; ` ` ` `} ` ` ` ` ` `// increment the timer as you exit the ` ` ` `// recursion for v ` ` ` `++timer; ` ` ` ` ` `// upgrade the outtime for that node ` ` ` `outtime[v] = timer; ` `} ` ` ` `// Returns true if 'u' and 'v' lie on same root to leaf path ` `// else false. ` `bool` `query(` `int` `u, ` `int` `v) ` `{ ` ` ` `return` `( (intime[u]<intime[v] && outtime[u]>outtime[v]) || ` ` ` `(intime[v]<intime[u] && outtime[v]>outtime[u]) ); ` `} ` ` ` `// Driver code ` `int` `main() ` `{ ` ` ` `// Let us create above shown tree ` ` ` `int` `n = 9; ` `// total number of nodes ` ` ` `vector<` `int` `> graph[n+1]; ` ` ` `graph[1].push_back(2); ` ` ` `graph[1].push_back(3); ` ` ` `graph[3].push_back(6); ` ` ` `graph[2].push_back(4); ` ` ` `graph[2].push_back(5); ` ` ` `graph[5].push_back(7); ` ` ` `graph[5].push_back(8); ` ` ` `graph[5].push_back(9); ` ` ` ` ` `// Start dfs (here root node is 1) ` ` ` `dfs(graph, 1); ` ` ` ` ` `// below are calls for few pairs of nodes ` ` ` `query(1, 5)? cout << ` `"Yes\n"` `: cout << ` `"No\n"` `; ` ` ` `query(2, 9)? cout << ` `"Yes\n"` `: cout << ` `"No\n"` `; ` ` ` `query(2, 6)? cout << ` `"Yes\n"` `: cout << ` `"No\n"` `; ` ` ` ` ` `return` `0; ` `} ` |

*chevron_right*

*filter_none*

## Python3

`# Python3 program to check if given ` `# pairs lie on same path or not. ` ` ` `# Does DFS of given graph and fills ` `# arrays intime[] and outtime[]. ` `# These arrays are used to answer ` `# given queries. ` `def` `dfs(graph, v): ` ` ` `global` `intime, outtime, visit, ` `MAX` `, timer ` ` ` `visit[v] ` `=` `True` ` ` ` ` `# Increment the timer as you enter ` ` ` `# the recursion for v ` ` ` `timer ` `+` `=` `1` ` ` ` ` `# Upgrade the in time for the vertex ` ` ` `intime[v] ` `=` `timer ` ` ` `it ` `=` `0` ` ` `while` `it < ` `len` `(graph[v]): ` ` ` `if` `(visit[graph[v][it]] ` `=` `=` `False` `): ` ` ` `dfs(graph, graph[v][it]) ` ` ` `it ` `+` `=` `1` ` ` ` ` `# increment the timer as you ` ` ` `# exit the recursion for v ` ` ` `timer ` `+` `=` `1` ` ` ` ` `# upgrade the outtime for that node ` ` ` `outtime[v] ` `=` `timer ` ` ` `# Returns true if 'u' and 'v' lie on ` `# same root to leaf path else false. ` `def` `query(u, v): ` ` ` `global` `intime, outtime, visit, ` `MAX` `, timer ` ` ` `return` `((intime[u] < intime[v] ` `and` ` ` `outtime[u] > outtime[v]) ` `or` ` ` `(intime[v] < intime[u] ` `and` ` ` `outtime[v] > outtime[u]) ) ` ` ` `# Driver code ` `MAX` `=` `100001` ` ` `# To keep track of visited vertices in DFS ` `visit ` `=` `[` `0` `] ` `*` `MAX` ` ` `# To store start and end time of ` `# all vertices during DFS. ` `intime ` `=` `[` `0` `] ` `*` `MAX` `outtime ` `=` `[` `0` `] ` `*` `MAX` ` ` `# initially timer is zero ` `timer ` `=` `0` ` ` `# Let us create above shown tree ` `n ` `=` `9` `# total number of nodes ` `graph ` `=` `[[] ` `for` `i ` `in` `range` `(n` `+` `1` `)] ` `graph[` `1` `].append(` `2` `) ` `graph[` `1` `].append(` `3` `) ` `graph[` `3` `].append(` `6` `) ` `graph[` `2` `].append(` `4` `) ` `graph[` `2` `].append(` `5` `) ` `graph[` `5` `].append(` `7` `) ` `graph[` `5` `].append(` `8` `) ` `graph[` `5` `].append(` `9` `) ` ` ` `# Start dfs (here root node is 1) ` `dfs(graph, ` `1` `) ` ` ` `# below are calls for few pairs of nodes ` `print` `(` `"Yes"` `) ` `if` `query(` `1` `, ` `5` `) ` `else` `print` `(` `"No"` `) ` `print` `(` `"Yes"` `) ` `if` `query(` `2` `, ` `9` `) ` `else` `print` `(` `"No"` `) ` `print` `(` `"Yes"` `) ` `if` `query(` `2` `, ` `6` `) ` `else` `print` `(` `"No"` `) ` ` ` `# This code is contributed by PranchalK ` |

*chevron_right*

*filter_none*

**Output:**

Yes Yes No

**Illustration:**

From the diagram below to understand more we can have some examples. DFS algorithm as modified above will result in the following intime and outtime for the vertex of the tree as labelled there. Now we will consider all the cases.

Case 1 : Nodes 2 and 4 : Node 2 has intime less than node 4 but since 4 is in its sub tree so it will have a greater exit time than 4 . Thus condition is valid and both are on same path.

Case 2 : Nodes 7 and 6 : Node 7 has intime less than node 6 but since both nodes are not in each other’s sub tree so their exit time does not follow the required condition.

This article is contributed by **Saurabh Joshi.** If you like GeeksforGeeks and would like to contribute, you can also write an article and mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.

Please write comments if you find anything incorrect, or you want to share more information about the topic discussed above

## Recommended Posts:

- Print the path between any two nodes of a tree | DFS
- Check if given path between two nodes of a graph represents a shortest paths
- Count the nodes of the tree which make a pangram when concatenated with the sub-tree nodes
- Minimum cost to reverse edges such that there is path between every pair of nodes
- XOR of all the nodes in the sub-tree of the given node
- Subtree of all nodes in a tree using DFS
- Number of special nodes in an n-ary tree
- Count the nodes in the given tree whose weight is even
- Print Nodes in Top View of Binary Tree
- Count the number of nodes at a given level in a tree using DFS
- Count the nodes of the given tree whose weight has X as a factor
- Count the nodes in the given tree whose sum of digits of weight is odd
- Count the nodes in the given tree whose weight is even parity
- Count the nodes in the given tree whose weight is a power of two
- Count the nodes in the given tree whose weight is prime