Skip to content
Related Articles

Related Articles

Improve Article

Count of all possible Paths in a Tree such that Node X does not appear before Node Y

  • Last Updated : 15 Sep, 2021

Given a Tree consisting of N nodes having values in the range [0, N – 1] and (N – 1) edges, and two nodes X and Y, the task is to find the number of possible paths in the Tree such that the node X does not appear before the node Y in the path.

Examples:

Input: N = 5, A = 2, B = 0, Edges[][] = { {0, 1}, {1, 2}, {1, 3}, {0, 4} } 
Output: 18 
Explanation: 
Since (X, Y) and (Y, X) are being considered different, so the count of all possible paths connecting any two pairs of vertices = 2 * 5C2 = 20. 
Out of these 20 pairs, those paths cannot be chosen, which consist of both nodes 2 and 0 as well as Node 2 appearing before Node 0. 
There are two such paths (colored as green) which are shown below:

So there are total 20 – 2 = 18 such paths.



Input: N = 9, X = 5, Y = 3, Edges[][] = { {0, 2}, {1, 2}, {2, 3}, {3, 4}, {4, 6}, {4, 5}, {5, 7}, {5, 8} } 
Output: 60 
Explanation: 
Since (X, Y) and (Y, X) are being considered different, so the count of all possible paths connecting any two pairs of vertices = N * (N – 1) = 9 * 8 = 72. 
On observing the diagram below, any path starting from a Node in the subtree of Node 5, denoted by black, connecting to the vertices passing through the Node 3, denoted by green, will always have 5 appearing before 3 in the path. 

Therefore, total number of possible paths = (Total Nodes grouped in black) * (Total Nodes grouped in green) = 3 * 4 = 12. 
Therefore, the final answer = 72 – 12 = 60  

Approach: 
The idea is to find the combination of node pairs that will always have the Node X appearing before Node Y in the path connecting them. Then, subtract the count of such pairs from the total number of possible node pairs = NC2. Consider node Y as the root node. Now any path which first encounters X and then Y, starts from the node in the subtree of node X and ends at a node in the sub-tree of node Y but not in the subtree of node W, where W is an immediate child of node Y and lies between X and Y in these paths.

Therefore, the final answer can be calculated by:

Count = N * (N – 1) – size_of_subtree(X) * (size_of_subtree(Y) – size_of_subtree(W))

If Y is taken as the root of the tree. Then, size_of_subtree(Y) = N.

Count = N * (N – 1) – size_of_subtree(X) * (N- size_of_subtree(W))



Follow the steps below to solve the problem:

  1. Initialize arrays subtree_size [], visited [] and check_subtree [] each of size N + 1. Initialize elements of visited [] as 0.
  2. Perform the DFS Traversal with Y as the root node to fill the check_subtree[] and subtree_size [] for each node. The check_subtree[] checks whether the subtree of the current node contains node X or not.
  3. Find the child(say node v) of Y which is in the path from X to Y. Initialize an integer variable say difference.
  4. Assign (total number of nodes – subtree_size[v] ) to difference.
  5. Return (N * (N – 1) ) – (subtree_size[A] * (difference)) as the answer.

Below is the implementation of the above approach:

C++




// C++ Program to implement
// the above approach
#include <bits/stdc++.h>
#define int long long int
using namespace std;
 
// Maximum number of nodes
const int NN = 3e5;
 
// Vector to store the tree
vector<int> G[NN + 1];
 
// Function to perform DFS Traversal
int dfs(int node, int A, int* subtree_size,
        int* visited, int* check_subtree)
{
    // Mark the node as visited
    visited[node] = true;
 
    // Initialize the subtree size
    // of each node as 1
    subtree_size[node] = 1;
 
    // If the node is same as A
    if (node == A) {
 
        // Mark check_subtree[node] as true
        check_subtree[node] = true;
    }
 
    // Otherwise
    else
        check_subtree[node] = false;
 
    // Iterate over the adjacent nodes
    for (int v : G[node]) {
 
        // If the adjacent node
        // is not visited
        if (!visited[v]) {
 
            // Update the size of the
            // subtree of current node
            subtree_size[node]
                += dfs(v, A, subtree_size,
                       visited, check_subtree);
 
            // Check if the subtree of
            // current node contains node A
            check_subtree[node] = check_subtree[node]
                                  | check_subtree[v];
        }
    }
 
    // Return size of subtree of node
    return subtree_size[node];
}
 
// Function to add edges to the tree
void addedge(int node1, int node2)
{
 
    G[node1].push_back(node2);
    G[node2].push_back(node1);
}
 
// Function to calculate the number of
// possible paths
int numberOfPairs(int N, int B, int A)
{
    // Stores the size of subtree
    // of each node
    int subtree_size[N + 1];
 
    // Stores which nodes are
    // visited
    int visited[N + 1];
 
    // Initialize all nodes as unvisited
    memset(visited, 0, sizeof(visited));
 
    // Stores if the subtree of
    // a node contains node A
    int check_subtree[N + 1];
 
    // DFS Call
    dfs(B, A, subtree_size,
        visited, check_subtree);
 
    // Stores the difference between
    // total number of nodes and
    // subtree size of an immediate
    // child of Y lies between the
    // path from A to B
    int difference;
 
    // Iterate over the adjacent nodes B
    for (int v : G[B]) {
 
        // If the node is in the path
        // from A to B
        if (check_subtree[v]) {
 
            // Calculate the difference
            difference = N - subtree_size[v];
 
            break;
        }
    }
 
    // Return the final answer
    return (N * (N - 1))
           - difference * (subtree_size[A]);
}
 
// Driver Code
int32_t main()
{
    int N = 9;
 
    int X = 5, Y = 3;
 
    // Insert Edges
    addedge(0, 2);
    addedge(1, 2);
    addedge(2, 3);
    addedge(3, 4);
    addedge(4, 6);
    addedge(4, 5);
    addedge(5, 7);
    addedge(5, 8);
 
    cout << numberOfPairs(N, Y, X);
 
    return 0;
}

Java




// Java Program to implement
// the above approach
import java.util.*;
class GFG{
 
// Maximum number of nodes
static int NN = (int) 3e5;
 
// Vector to store the tree
static Vector<Integer> []G = new Vector[NN + 1];
 
// Function to perform DFS Traversal
static int dfs(int node, int A, int[] subtree_size,
               int[] visited, int[] check_subtree)
{
    // Mark the node as visited
    visited[node] = 1;
 
    // Initialize the subtree size
    // of each node as 1
    subtree_size[node] = 1;
 
    // If the node is same as A
    if (node == A)
    {
 
        // Mark check_subtree[node] as true
        check_subtree[node] = 1;
    }
 
    // Otherwise
    else
        check_subtree[node] = 0;
 
    // Iterate over the adjacent nodes
    for (int v : G[node])
    {
 
        // If the adjacent node
        // is not visited
        if (visited[v] == 0)
        {
 
            // Update the size of the
            // subtree of current node
            subtree_size[node] += dfs(v, A, subtree_size,
                                      visited, check_subtree);
 
            // Check if the subtree of
            // current node contains node A
            check_subtree[node] = check_subtree[node] |
                                    check_subtree[v];
        }
    }
 
    // Return size of subtree of node
    return subtree_size[node];
}
 
// Function to add edges to the tree
static void addedge(int node1, int node2)
{
    G[node1].add(node2);
    G[node2].add(node1);
}
 
// Function to calculate the number of
// possible paths
static int numberOfPairs(int N, int B, int A)
{
    // Stores the size of subtree
    // of each node
    int []subtree_size = new int[N + 1];
 
    // Stores which nodes are
    // visited
    int []visited = new int[N + 1];
 
 
    // Stores if the subtree of
    // a node contains node A
    int []check_subtree = new int[N + 1];
 
    // DFS Call
    dfs(B, A, subtree_size,
        visited, check_subtree);
 
    // Stores the difference between
    // total number of nodes and
    // subtree size of an immediate
    // child of Y lies between the
    // path from A to B
    int difference = 0;
 
    // Iterate over the adjacent nodes B
    for (int v : G[B])
    {
 
        // If the node is in the path
        // from A to B
        if (check_subtree[v] > 0)
        {
 
            // Calculate the difference
            difference = N - subtree_size[v];
 
            break;
        }
    }
 
    // Return the final answer
    return (N * (N - 1)) -
              difference * (subtree_size[A]);
}
 
// Driver Code
public static void main(String[] args)
{
    int N = 9;
 
    int X = 5, Y = 3;
     
    for (int i = 0; i < G.length; i++)
        G[i] = new Vector<Integer>();
   
    // Insert Edges
    addedge(0, 2);
    addedge(1, 2);
    addedge(2, 3);
    addedge(3, 4);
    addedge(4, 6);
    addedge(4, 5);
    addedge(5, 7);
    addedge(5, 8);
 
    System.out.print(numberOfPairs(N, Y, X));
}
}
 
// This code is contributed by sapnasingh4991

Python3




# Python3 program to implement
# the above approach
 
# Maximum number of nodes
NN = int(3e5)
 
# Vector to store the tree
G = []
for i in range(NN + 1):
    G.append([])
 
# Function to perform DFS Traversal
def dfs(node, A, subtree_size,
        visited, check_subtree):
 
    # Mark the node as visited
    visited[node] = True
 
    # Initialize the subtree size
    # of each node as 1
    subtree_size[node] = 1
 
    # If the node is same as A
    if (node == A):
 
        # Mark check_subtree[node] as true
        check_subtree[node] = True
 
    # Otherwise
    else:
        check_subtree[node] = False
 
    # Iterate over the adjacent nodes
    for v in G[node]:
 
        # If the adjacent node
        # is not visited
        if (not visited[v]):
 
            # Update the size of the
            # subtree of current node
            subtree_size[node] += dfs(v, A,
                                      subtree_size,
                                      visited,
                                      check_subtree)
 
            # Check if the subtree of
            # current node contains node A
            check_subtree[node] = (check_subtree[node] |
                                   check_subtree[v])
 
    # Return size of subtree of node
    return subtree_size[node]
 
# Function to add edges to the tree
def addedge(node1, node2):
 
    G[node1] += [node2]
    G[node2] += [node1]
 
# Function to calculate the number of
# possible paths
def numberOfPairs(N, B, A):
 
    # Stores the size of subtree
    # of each node
    subtree_size = [0] * (N + 1)
 
    # Stores which nodes are
    # visited
    visited = [0] * (N + 1)
 
    # Stores if the subtree of
    # a node contains node A
    check_subtree = [0] * (N + 1)
 
    # DFS Call
    dfs(B, A, subtree_size,
        visited, check_subtree)
 
    # Stores the difference between
    # total number of nodes and
    # subtree size of an immediate
    # child of Y lies between the
    # path from A to B
    difference = 0
 
    # Iterate over the adjacent nodes B
    for v in G[B]:
 
        # If the node is in the path
        # from A to B
        if (check_subtree[v]):
 
            # Calculate the difference
            difference = N - subtree_size[v]
            break
 
    # Return the final answer
    return ((N * (N - 1)) -
               difference * (subtree_size[A]))
 
# Driver Code
N = 9
X = 5
Y = 3
 
# Insert Edges
addedge(0, 2)
addedge(1, 2)
addedge(2, 3)
addedge(3, 4)
addedge(4, 6)
addedge(4, 5)
addedge(5, 7)
addedge(5, 8)
 
# Function call
print(numberOfPairs(N, Y, X))
 
# This code is contributed by Shivam Singh

C#




// C# Program to implement
// the above approach
using System;
using System.Collections.Generic;
 
class GFG{
 
// Maximum number of nodes
static int NN = (int) 3e5;
 
// List to store the tree
static List<int> []G = new List<int>[NN + 1];
 
// Function to perform DFS Traversal
static int dfs(int node, int A, int[] subtree_size,
               int[] visited, int[] check_subtree)
{
    // Mark the node as visited
    visited[node] = 1;
 
    // Initialize the subtree size
    // of each node as 1
    subtree_size[node] = 1;
 
    // If the node is same as A
    if (node == A)
    {
 
        // Mark check_subtree[node] as true
        check_subtree[node] = 1;
    }
 
    // Otherwise
    else
        check_subtree[node] = 0;
 
    // Iterate over the adjacent nodes
    foreach (int v in G[node])
    {
 
        // If the adjacent node
        // is not visited
        if (visited[v] == 0)
        {
 
            // Update the size of the
            // subtree of current node
            subtree_size[node] += dfs(v, A, subtree_size,
                                      visited, check_subtree);
 
            // Check if the subtree of
            // current node contains node A
            check_subtree[node] = check_subtree[node] |
                                    check_subtree[v];
        }
    }
 
    // Return size of subtree of node
    return subtree_size[node];
}
 
// Function to add edges to the tree
static void addedge(int node1, int node2)
{
    G[node1].Add(node2);
    G[node2].Add(node1);
}
 
// Function to calculate the number of
// possible paths
static int numberOfPairs(int N, int B, int A)
{
    // Stores the size of subtree
    // of each node
    int []subtree_size = new int[N + 1];
 
    // Stores which nodes are
    // visited
    int []visited = new int[N + 1];
 
 
    // Stores if the subtree of
    // a node contains node A
    int []check_subtree = new int[N + 1];
 
    // DFS Call
    dfs(B, A, subtree_size,
        visited, check_subtree);
 
    // Stores the difference between
    // total number of nodes and
    // subtree size of an immediate
    // child of Y lies between the
    // path from A to B
    int difference = 0;
 
    // Iterate over the adjacent nodes B
    foreach (int v in G[B])
    {
 
        // If the node is in the path
        // from A to B
        if (check_subtree[v] > 0)
        {
 
            // Calculate the difference
            difference = N - subtree_size[v];
 
            break;
        }
    }
 
    // Return the readonly answer
    return (N * (N - 1)) -
              difference * (subtree_size[A]);
}
 
// Driver Code
public static void Main(String[] args)
{
    int N = 9;
 
    int X = 5, Y = 3;
     
    for (int i = 0; i < G.Length; i++)
        G[i] = new List<int>();
   
    // Insert Edges
    addedge(0, 2);
    addedge(1, 2);
    addedge(2, 3);
    addedge(3, 4);
    addedge(4, 6);
    addedge(4, 5);
    addedge(5, 7);
    addedge(5, 8);
 
    Console.Write(numberOfPairs(N, Y, X));
}
}
 
 
// This code is contributed by sapnasingh4991

Javascript




<script>
    // Javascript Program to implement the above approach
     
    // Maximum number of nodes
    let NN = 3e5;
 
    // Vector to store the tree
    let G = new Array(NN + 1);
 
    // Function to perform DFS Traversal
    function dfs(node, A, subtree_size, visited, check_subtree)
    {
        // Mark the node as visited
        visited[node] = 1;
 
        // Initialize the subtree size
        // of each node as 1
        subtree_size[node] = 1;
 
        // If the node is same as A
        if (node == A)
        {
 
            // Mark check_subtree[node] as true
            check_subtree[node] = 1;
        }
 
        // Otherwise
        else
            check_subtree[node] = 0;
 
        // Iterate over the adjacent nodes
        for (let v = 0; v < G[node].length; v++)
        {
 
            // If the adjacent node
            // is not visited
            if (visited[G[node][v]] == 0)
            {
 
                // Update the size of the
                // subtree of current node
                subtree_size[node] += dfs(G[node][v], A, subtree_size,
                                          visited, check_subtree);
 
                // Check if the subtree of
                // current node contains node A
                check_subtree[node] = check_subtree[node] |
                                        check_subtree[G[node][v]];
            }
        }
 
        // Return size of subtree of node
        return subtree_size[node];
    }
 
    // Function to add edges to the tree
    function addedge(node1, node2)
    {
        G[node1].push(node2);
        G[node2].push(node1);
    }
 
    // Function to calculate the number of
    // possible paths
    function numberOfPairs(N, B, A)
    {
        // Stores the size of subtree
        // of each node
        let subtree_size = new Array(N + 1);
        subtree_size.fill(0);
 
        // Stores which nodes are
        // visited
        let visited = new Array(N + 1);
        visited.fill(0);
 
 
        // Stores if the subtree of
        // a node contains node A
        let check_subtree = new Array(N + 1);
        check_subtree.fill(0);
 
        // DFS Call
        dfs(B, A, subtree_size, visited, check_subtree);
 
        // Stores the difference between
        // total number of nodes and
        // subtree size of an immediate
        // child of Y lies between the
        // path from A to B
        let difference = 0;
 
        // Iterate over the adjacent nodes B
        for (let v = 0; v < G[B].length; v++)
        {
 
            // If the node is in the path
            // from A to B
            if (check_subtree[G[B][v]] > 0)
            {
 
                // Calculate the difference
                difference = N - subtree_size[G[B][v]];
 
                break;
            }
        }
 
        // Return the final answer
        return (N * (N - 1)) -
                  difference * (subtree_size[A]);
    }
     
    let N = 9;
   
    let X = 5, Y = 3;
       
    for (let i = 0; i < G.length; i++)
        G[i] = [];
     
    // Insert Edges
    addedge(0, 2);
    addedge(1, 2);
    addedge(2, 3);
    addedge(3, 4);
    addedge(4, 6);
    addedge(4, 5);
    addedge(5, 7);
    addedge(5, 8);
   
    document.write(numberOfPairs(N, Y, X));
 
</script>
Output: 
60

 

Time Complexity: O(N) 
Auxiliary Space: O(N)
 

 

Attention reader! Don’t stop learning now. Get hold of all the important DSA concepts with the DSA Self Paced Course at a student-friendly price and become industry ready.  To complete your preparation from learning a language to DS Algo and many more,  please refer Complete Interview Preparation Course.

In case you wish to attend live classes with experts, please refer DSA Live Classes for Working Professionals and Competitive Programming Live for Students.




My Personal Notes arrow_drop_up
Recommended Articles
Page :