Given a tree consisting of n nodes (1,2,...,n) and n-1 lines describing the edges between nodes u and v. The task is to determine for each node the maximum distance to another node.
Example:
Input: n= 5, v= {{1,2}, {1,3}, {3,4}, {3,5}}
Output: 2 3 2 3 3
Explanation:
Tree
The farthest node from node 1 is node 4, with a distance of 2. The farthest node from node 2 is node 4, with a distance of 3. The farthest node from node 3 is node 2, with a distance of 2. The farthest node from node 4 is node 2, with a distance of 3. The farthest node from node 5 is node 2, with a distance of 3.
Approach: To solve the problem, follow the idea below:
The idea is to find the diameter (maximum distance between any two nodes) of the tree and use it to calculate the maximum distance for each node to any other node. Consider any node u in the tree. The farthest node from u must be the either end of the diameter of the tree. This is because any path from u to a node not on the diameter could be made longer by extending it to a node on the diameter. Use BFS to find the farthest node from 1 and store it in di_st. Again use BFS to find the farthest node from di_st and store it in di_end, these nodes are farthest apart. Then use DFS to calculate the distance of each node from di_st and di_end. The maximum distance for a node to any other node is the maximum of these two distances.
Step-by-step algorithm:
Create an adjacency list adj to represent the tree.
Use BFS to find the farthest node from any node, take 1 and store it in di_st.
Again use BFS to find the farthest node from di_st and store it in di_end.
Use DFS to calculate the distance of each node from di_st.
Store the distance of the node from the starting node in the first column of vector dp.
Recursively call for the child node and increase the distance by 1.
Again use DFS to calculate the distance of each node from di_end.
Store the distance of the node from the starting node in the second column of vector dp.
Recursively call for the child node and increase the distance by 1.
For each node, find the maximum distance by taking the maximum of the distance calculated from dt_st and distance calculated from dt_end.
Return the maximum distances in a vector mxdist.
Below is the implementation of the above algorithm:
C++
// C++ code#include<bits/stdc++.h>usingnamespacestd;// Depth-first search function to calculate the distance of// each node from a given nodevoiddfs(intparent,intnode,intdist,intc,vector<int>adj[],vector<vector<int>>&dp){// Store the distance of the node from the starting nodedp[node][c]=dist;// Iterate over all the adjacent nodesfor(autochild:adj[node])// If the adjacent node is not the parentif(child!=parent)// Recursively call for the child node and// increase the distance by 1dfs(node,child,dist+1,c,adj,dp);}// Breadth-first search function to find the node at the// maximum distance from a given nodeintbfs(intnode,intn,vector<int>adj[]){// Queue to store the node and its distance from the// starting nodequeue<pair<int,int>>q;// Push the starting node into the queue with distance 0q.push({node,0});// Visited array to keep track of visited nodesvector<bool>vis(n+1,false);// Mark the starting node as visitedvis[node]=true;intu,dist;while(!q.empty()){// Node at the front of the queueu=q.front().first;// Distance of the node from the starting nodedist=q.front().second;// Remove the node from the queueq.pop();// Iterate over all the adjacent nodesfor(autochild:adj[u]){if(!vis[child]){// Push the node into the queueq.push({child,dist+1});// Mark the node as visitedvis[child]=true;}}}// Return the node at the maximum distancereturnu;}vector<int>treedistance1(intn,vector<vector<int>>&v){vector<int>adj[n+1];for(autoi:v){adj[i[0]].push_back(i[1]);adj[i[1]].push_back(i[0]);}vector<int>mxdist;// Node at the maximum distance from node 1intdi_st=bfs(1,n,adj);// Node at the maximum distance from node di_stintdi_end=bfs(di_st,n,adj);// 2D vector to store the maximum distance of each nodevector<vector<int>>dp(n+1,vector<int>(2,0));// DFS from di_stdfs(0,di_st,0,0,adj,dp);// DFS from di_enddfs(0,di_end,0,1,adj,dp);// Take the max distancefor(inti=1;i<=n;i++)mxdist.push_back(max(dp[i][0],dp[i][1]));returnmxdist;}// Driver Codeintmain(){intn=5;vector<vector<int>>v={{1,2},{1,3},{3,4},{3,5}};vector<int>mxdist=treedistance1(n,v);if(n==1){cout<<0<<endl;}for(autoi:mxdist)cout<<i<<" ";return0;}
Java
importjava.util.*;publicclassTreeDistance{// Depth-first search function to calculate the distance of// each node from a given nodestaticvoiddfs(intparent,intnode,intdist,intc,ArrayList<Integer>[]adj,int[][]dp){// Store the distance of the node from the starting nodedp[node][c]=dist;// Iterate over all the adjacent nodesfor(intchild:adj[node]){// If the adjacent node is not the parentif(child!=parent){// Recursively call for the child node and// increase the distance by 1dfs(node,child,dist+1,c,adj,dp);}}}// Breadth-first search function to find the node at the// maximum distance from a given nodestaticintbfs(intnode,intn,ArrayList<Integer>[]adj){// Queue to store the node and its distance from the// starting nodeQueue<int[]>q=newLinkedList<>();// Push the starting node into the queue with distance 0q.offer(newint[]{node,0});// Visited array to keep track of visited nodesboolean[]vis=newboolean[n+1];// Mark the starting node as visitedvis[node]=true;intu=0,dist=0;while(!q.isEmpty()){// Node at the front of the queueint[]curr=q.poll();u=curr[0];// Distance of the node from the starting nodedist=curr[1];// Iterate over all the adjacent nodesfor(intchild:adj[u]){if(!vis[child]){// Push the node into the queueq.offer(newint[]{child,dist+1});// Mark the node as visitedvis[child]=true;}}}// Return the node at the maximum distancereturnu;}publicstaticArrayList<Integer>treeDistance1(intn,ArrayList<int[]>v){ArrayList<Integer>[]adj=newArrayList[n+1];for(inti=1;i<=n;i++){adj[i]=newArrayList<>();}for(int[]edge:v){adj[edge[0]].add(edge[1]);adj[edge[1]].add(edge[0]);}ArrayList<Integer>mxdist=newArrayList<>();// Node at the maximum distance from node 1intdi_st=bfs(1,n,adj);// Node at the maximum distance from node di_stintdi_end=bfs(di_st,n,adj);// 2D array to store the maximum distance of each nodeint[][]dp=newint[n+1][2];// DFS from di_stdfs(0,di_st,0,0,adj,dp);// DFS from di_enddfs(0,di_end,0,1,adj,dp);// Take the max distancefor(inti=1;i<=n;i++)mxdist.add(Math.max(dp[i][0],dp[i][1]));returnmxdist;}// Driver Codepublicstaticvoidmain(String[]args){intn=5;ArrayList<int[]>v=newArrayList<>(Arrays.asList(newint[]{1,2},newint[]{1,3},newint[]{3,4},newint[]{3,5}));ArrayList<Integer>mxdist=treeDistance1(n,v);if(n==1){System.out.println(0);}for(inti:mxdist)System.out.print(i+" ");}}// This code is contributed by shivamgupta0987654321
Python3
# Importing the required librariesfromcollectionsimportdeque# Depth-first search function to calculate the distance of# each node from a given nodedefdfs(parent,node,dist,c,adj,dp):# Store the distance of the node from the starting nodedp[node][c]=dist# Iterate over all the adjacent nodesforchildinadj[node]:# If the adjacent node is not the parentifchild!=parent:# Recursively call for the child node and# increase the distance by 1dfs(node,child,dist+1,c,adj,dp)# Breadth-first search function to find the node at the# maximum distance from a given nodedefbfs(node,n,adj):# Queue to store the node and its distance from the# starting nodeq=deque([(node,0)])# Visited array to keep track of visited nodesvis=[False]*(n+1)# Mark the starting node as visitedvis[node]=Truewhileq:# Node at the front of the queueu,dist=q.popleft()# Iterate over all the adjacent nodesforchildinadj[u]:ifnotvis[child]:# Push the node into the queueq.append((child,dist+1))# Mark the node as visitedvis[child]=True# Return the node at the maximum distancereturnudeftreedistance1(n,v):adj=[[]for_inrange(n+1)]foriinv:adj[i[0]].append(i[1])adj[i[1]].append(i[0])mxdist=[]# Node at the maximum distance from node 1di_st=bfs(1,n,adj)# Node at the maximum distance from node di_stdi_end=bfs(di_st,n,adj)# 2D vector to store the maximum distance of each nodedp=[[0,0]for_inrange(n+1)]# DFS from di_stdfs(0,di_st,0,0,adj,dp)# DFS from di_enddfs(0,di_end,0,1,adj,dp)# Take the max distanceforiinrange(1,n+1):mxdist.append(max(dp[i][0],dp[i][1]))returnmxdist# Driver Codedefmain():n=5v=[[1,2],[1,3],[3,4],[3,5]]mxdist=treedistance1(n,v)ifn==1:print(0)foriinmxdist:print(i,end=" ")if__name__=="__main__":main()
JavaScript
// Depth-first search function to calculate the distance of// each node from a given nodefunctiondfs(parent,node,dist,c,adj,dp){// Store the distance of the node from the starting nodedp[node][c]=dist;// Iterate over all the adjacent nodesfor(letchildofadj[node]){// If the adjacent node is not the parentif(child!==parent){// Recursively call for the child node and// increase the distance by 1dfs(node,child,dist+1,c,adj,dp);}}}// Breadth-first search function to find the node at the// maximum distance from a given nodefunctionbfs(node,n,adj){// Queue to store the node and its distance from the// starting nodeletq=[];// Push the starting node into the queue with distance 0q.push([node,0]);// Visited array to keep track of visited nodesletvis=newArray(n+1).fill(false);// Mark the starting node as visitedvis[node]=true;letu,dist;while(q.length!==0){// Node at the front of the queue[u,dist]=q.shift();// Iterate over all the adjacent nodesfor(letchildofadj[u]){if(!vis[child]){// Push the node into the queueq.push([child,dist+1]);// Mark the node as visitedvis[child]=true;}}}// Return the node at the maximum distancereturnu;}functiontreedistance1(n,v){letadj=newArray(n+1).fill(null).map(()=>[]);for(letiofv){adj[i[0]].push(i[1]);adj[i[1]].push(i[0]);}letmxdist=[];// Node at the maximum distance from node 1letdi_st=bfs(1,n,adj);// Node at the maximum distance from node di_stletdi_end=bfs(di_st,n,adj);// 2D array to store the maximum distance of each nodeletdp=newArray(n+1).fill(null).map(()=>[0,0]);// DFS from di_stdfs(0,di_st,0,0,adj,dp);// DFS from di_enddfs(0,di_end,0,1,adj,dp);// Take the max distancefor(leti=1;i<=n;i++)mxdist.push(Math.max(dp[i][0],dp[i][1]));returnmxdist;}// Driver Codefunctionmain(){letn=5;letv=[[1,2],[1,3],[3,4],[3,5]];letmxdist=treedistance1(n,v);letoutput="";// Initialize an empty string to store the outputif(n===1){output+="0 ";// Append "0" to the output string}else{for(letiofmxdist)output+=i+" ";// Append each distance followed by a space to the output string}console.log(output.trim());// Print the output string after trimming any leading/trailing spaces}// Call the main functionmain();
Output
2 3 2 3 3
Time Complexity: O(n), where n is the number of node. Auxiliary Space: O(n), where n is the number of node.