Check if a path exists in a tree with K vertices present or are at most at a distance D

Given a tree with N vertices numbered [0, n – 1], K vertices and a distance D, the task is to find whether there is a path from the root to some vertex such that each of the K vertices belongs to the path or are at most at a distance D from the path.

Examples:

Input: 
             0
           /   \
         /       \
       1           2
     /   \        /  \
   /       \     /     \
  3         4   5        8
               /  \        
              /     \
             6       7
                    /
                   /
                  9
K = {6, 7, 8, 5}, D = 1
Output: YES
Explanation: 
The path ( 0 - 2 - 5 - 7 )
satisfies the condition. Vertices 5 
and 7 are a part of the path. 
Vertex 6 is the child of vertex 
5 and 8 is the child of 2. 

Input:
             0
           /   \
         /       \
       1           2
     /   \        /  \
   /       \     /     \
  3         4   5        8
   \           /  \        
    \         /     \
     10      6       7
                    /
                   /
                  9
K = {10, 9, 8, 5}, D = 2
Output: NO
Explanation: 
No such path exists that satisfies the condition.

Approach:

  • For every vertex, store their respective parent and depth.
  • Select the deepest vertex from the given K vertices
  • Keep replacing the K vertices except the root and the deepest vertex by its parent D times
  • If the current set of K vertices can form a continuous path, then the answer is Yes or No otherwise.

Below code is the implementation of the above approach:

C++

filter_none

edit
close

play_arrow

link
brightness_4
code

// C++ implementation of above approach
  
#include <bits/stdc++.h>
using namespace std;
  
// Class to represent the Tree
class Tree {
  
    int T;
  
    // Stores the timing of traversals
    vector<int> parent;
  
    // Stores the parent of each vertex
    vector<int> depth;
  
    // Stores the depth of each vertex
    vector<int> tin;
  
    // Stores the time to reach
    // every vertex
    vector<int> tout;
  
    // Stores the time of leaving
    // every vertex after DFS calls
    // from its children
    vector<vector<int> > edges;
  
    // Store the edges
  
public:
    // Constructor
    Tree(int n)
    {
        T = 0;
        parent = depth = vector<int>(n);
        tin = tout = vector<int>(n);
        edges = vector<vector<int> >(n);
    }
  
    // Adding edges
    void addEdge(int u, int v)
    {
        edges[u].push_back(v);
        edges[v].push_back(u);
    }
  
    void dfs(int v, int p = -1, int d = 0)
    {
        // Store the time to reach vertex v
        tin[v] = T++;
  
        // Store the parent of vertex v
        parent[v] = p;
  
        // Store the depth of vertex v
        depth[v] = d;
  
        // Run DFS for all its children of v
        for (auto i : edges[v]) {
            if (i == p)
                continue;
  
            dfs(i, v, d + 1);
        }
  
        // Store the leaving time
        // of vertex v
        tout[v] = T++;
    }
  
    // Checks and returns whether vertex
    // v is parent of vertex u or not
    bool checkTiming(int v, int u)
    {
        if (tin[v] <= tin[u]
            && tout[u] <= tout[v])
            return true;
  
        return false;
    }
  
    // Checks and returns if the path exists
    void pathExistence(vector<int> k, int d)
    {
        int deepest_vertex = k[0];
  
        // Find the deepest vertex among the
        // given K vertices
        for (int i = 0; i < k.size(); i++) {
            if (depth[k[i]] > depth[deepest_vertex])
                deepest_vertex = k[i];
        }
  
        // Replace each of the K vertices
        // except for the root and the
        // deepest vertex
        for (int i = 0; i < k.size(); i++) {
            if (k[i] == deepest_vertex)
                continue;
  
            int count = d;
  
            while (count > 0) {
  
                // Stop when root
                // has been reached
                if (parent[k[i]] == -1)
                    break;
  
                k[i] = parent[k[i]];
                count--;
            }
        }
  
        bool ans = true;
  
        // Check if each of the K-1 vertices
        // are a parent of the deepest vertex
        for (auto i : k)
            ans &= checkTiming(i, deepest_vertex);
  
        if (ans)
            cout << "Yes" << endl;
        else
            cout << "No" << endl;
    }
};
  
// Driver Code
int main()
{
    Tree t(11);
  
    t.addEdge(0, 1);
    t.addEdge(0, 2);
    t.addEdge(1, 3);
    t.addEdge(1, 4);
    t.addEdge(2, 5);
    t.addEdge(2, 8);
    t.addEdge(5, 6);
    t.addEdge(4, 10);
    t.addEdge(3, 7);
    t.addEdge(3, 9);
  
    t.dfs(0);
  
    vector<int> k = { 2, 6, 8, 5 };
  
    int d = 2;
  
    t.pathExistence(k, d);
  
    return 0;
}

chevron_right


Output:

Yes

competitive-programming-img




My Personal Notes arrow_drop_up

Recommended Posts:


Check out this Author's contributed articles.

If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.

Please Improve this article if you find anything incorrect by clicking on the "Improve Article" button below.



Improved By : Akanksha_Rai