Given a Tree with N nodes, the task is to find a triplet of nodes (a, b, c) such that the number of nodes covered in the path connecting these nodes is maximum. (Count a node only once).
Examples:
Input: N = 4
Edge Set:
1 2
1 3
1 4
Output: (2, 3, 4)
(2, 3, 4) as path between (2, 3) covers nodes 2, 1, 3 and path between (3, 4) covers nodes 3, 1, 4. Hence all nodes are covered.
The Red Path in Tree denotes the path between 2 to 3 node which covers node 1, 2, 3. The green path denotes path between (3, 4) which covers node 3, 1, 4.
Input: N = 9
Edge Set :
1 2
2 3
3 4
4 5
5 6
2 7
7 8
4 9
Output: (6, 8, 1)
Approach:
- One important point to notice is, two of the points in triplet must be the end of diameter of tree to cover maximum of the points.
- We need to find the longest length branch stick to the diameter.
- Now for 3rd node, apply DFS along with maintaining the depth for each node (DFS in all directions other than on the Diameter Path Selected ) to all the nodes present on the path of Diameter, the node which is at the farthest distance, would be considered as the 3rd node, as it covers the maximum node other than already covered by the Diameter. Diameter of Tree using DFS
Below is the implementation of the above approach:
// C++ implementation of the approach #include <bits/stdc++.h> #define ll long long int #define MAX 100005 using namespace std;
vector< int > adjacent[MAX];
bool visited[MAX];
// To store the required nodes int startnode, endnode, thirdnode;
int maxi = -1, N;
// Parent array to retrace the nodes int parent[MAX];
// Visited array to prevent DFS // in direction on Diameter path bool vis[MAX];
// DFS function to find the startnode void dfs( int u, int count)
{ visited[u] = true ;
int temp = 0;
for ( int i = 0; i < adjacent[u].size(); i++) {
if (!visited[adjacent[u][i]]) {
temp++;
dfs(adjacent[u][i], count + 1);
}
}
if (temp == 0) {
if (maxi < count) {
maxi = count;
startnode = u;
}
}
} // DFS function to find the endnode // of diameter and maintain the parent array void dfs1( int u, int count)
{ visited[u] = true ;
int temp = 0;
for ( int i = 0; i < adjacent[u].size(); i++) {
if (!visited[adjacent[u][i]]) {
temp++;
parent[adjacent[u][i]] = u;
dfs1(adjacent[u][i], count + 1);
}
}
if (temp == 0) {
if (maxi < count) {
maxi = count;
endnode = u;
}
}
} // DFS function to find the end node // of the Longest Branch to Diameter void dfs2( int u, int count)
{ visited[u] = true ;
int temp = 0;
for ( int i = 0; i < adjacent[u].size(); i++) {
if (!visited[adjacent[u][i]]
&& !vis[adjacent[u][i]]) {
temp++;
dfs2(adjacent[u][i], count + 1);
}
}
if (temp == 0) {
if (maxi < count) {
maxi = count;
thirdnode = u;
}
}
} // Function to find the required nodes void findNodes()
{ // To find start node of diameter
dfs(1, 0);
for ( int i = 0; i <= N; i++)
visited[i] = false ;
maxi = -1;
// To find end node of diameter
dfs1(startnode, 0);
for ( int i = 0; i <= N; i++)
visited[i] = false ;
// x is the end node of diameter
int x = endnode;
vis[startnode] = true ;
// Mark all the nodes on diameter
// using back tracking
while (x != startnode) {
vis[x] = true ;
x = parent[x];
}
maxi = -1;
// Find the end node of longest
// branch to diameter
for ( int i = 1; i <= N; i++) {
if (vis[i])
dfs2(i, 0);
}
} // Driver code int main()
{ N = 4;
adjacent[1].push_back(2);
adjacent[2].push_back(1);
adjacent[1].push_back(3);
adjacent[3].push_back(1);
adjacent[1].push_back(4);
adjacent[4].push_back(1);
findNodes();
cout << "(" << startnode << ", " << endnode
<< ", " << thirdnode << ")" ;
return 0;
} |
// Java implementation of the approach import java.util.*;
class GFG
{ static int MAX = 100005 ;
static Vector<Vector<Integer>> adjacent = new
Vector<Vector<Integer>> ();
static boolean visited[] = new boolean [MAX];
// To store the required nodes static int startnode, endnode, thirdnode;
static int maxi = - 1 , N;
// Parent array to retrace the nodes static int parent[] = new int [MAX];
// Visited array to prevent DFS // in direction on Diameter path static boolean vis[] = new boolean [MAX];
// DFS function to find the startnode static void dfs( int u, int count)
{ visited[u] = true ;
int temp = 0 ;
for ( int i = 0 ; i < adjacent.get(u).size(); i++)
{
if (!visited[adjacent.get(u).get(i)])
{
temp++;
dfs(adjacent.get(u).get(i), count + 1 );
}
}
if (temp == 0 )
{
if (maxi < count)
{
maxi = count;
startnode = u;
}
}
} // DFS function to find the endnode // of diameter and maintain the parent array static void dfs1( int u, int count)
{ visited[u] = true ;
int temp = 0 ;
for ( int i = 0 ; i < adjacent.get(u).size(); i++)
{
if (!visited[adjacent.get(u).get(i)])
{
temp++;
parent[adjacent.get(u).get(i)] = u;
dfs1(adjacent.get(u).get(i), count + 1 );
}
}
if (temp == 0 )
{
if (maxi < count)
{
maxi = count;
endnode = u;
}
}
} // DFS function to find the end node // of the Longest Branch to Diameter static void dfs2( int u, int count)
{ visited[u] = true ;
int temp = 0 ;
for ( int i = 0 ; i < adjacent.get(u).size(); i++)
{
if (!visited[adjacent.get(u).get(i)] &&
!vis[adjacent.get(u).get(i)])
{
temp++;
dfs2(adjacent.get(u).get(i), count + 1 );
}
}
if (temp == 0 )
{
if (maxi < count)
{
maxi = count;
thirdnode = u;
}
}
} // Function to find the required nodes static void findNodes()
{ // To find start node of diameter
dfs( 1 , 0 );
for ( int i = 0 ; i <= N; i++)
visited[i] = false ;
maxi = - 1 ;
// To find end node of diameter
dfs1(startnode, 0 );
for ( int i = 0 ; i <= N; i++)
visited[i] = false ;
// x is the end node of diameter
int x = endnode;
vis[startnode] = true ;
// Mark all the nodes on diameter
// using back tracking
while (x != startnode)
{
vis[x] = true ;
x = parent[x];
}
maxi = - 1 ;
// Find the end node of longest
// branch to diameter
for ( int i = 1 ; i <= N; i++)
{
if (vis[i])
dfs2(i, 0 );
}
} // Driver code public static void main(String args[])
{ for ( int i = 0 ; i < MAX; i++)
adjacent.add( new Vector<Integer>());
N = 4 ;
adjacent.get( 1 ).add( 2 );
adjacent.get( 2 ).add( 1 );
adjacent.get( 1 ).add( 3 );
adjacent.get( 3 ).add( 1 );
adjacent.get( 1 ).add( 4 );
adjacent.get( 4 ).add( 1 );
findNodes();
System.out.print( "(" + startnode + ", " +
endnode + ", " +
thirdnode + ")" );
} } // This code is contributed by Arnab Kundu |
# Python3 implementation of the approach MAX = 100005
adjacent = [[] for i in range ( MAX )]
visited = [ False ] * MAX
# To store the required nodes startnode = endnode = thirdnode = None
maxi, N = - 1 , None
# Parent array to retrace the nodes parent = [ None ] * MAX
# Visited array to prevent DFS # in direction on Diameter path vis = [ False ] * MAX
# DFS function to find the startnode def dfs(u, count):
visited[u] = True
temp = 0
global startnode, maxi
for i in range ( 0 , len (adjacent[u])):
if not visited[adjacent[u][i]]:
temp + = 1
dfs(adjacent[u][i], count + 1 )
if temp = = 0 :
if maxi < count:
maxi = count
startnode = u
# DFS function to find the endnode of # diameter and maintain the parent array def dfs1(u, count):
visited[u] = True
temp = 0
global endnode, maxi
for i in range ( 0 , len (adjacent[u])):
if not visited[adjacent[u][i]]:
temp + = 1
parent[adjacent[u][i]] = u
dfs1(adjacent[u][i], count + 1 )
if temp = = 0 :
if maxi < count:
maxi = count
endnode = u
# DFS function to find the end node # of the Longest Branch to Diameter def dfs2(u, count):
visited[u] = True
temp = 0
global thirdnode, maxi
for i in range ( 0 , len (adjacent[u])):
if ( not visited[adjacent[u][i]] and
not vis[adjacent[u][i]]):
temp + = 1
dfs2(adjacent[u][i], count + 1 )
if temp = = 0 :
if maxi < count:
maxi = count
thirdnode = u
# Function to find the required nodes def findNodes():
# To find start node of diameter
dfs( 1 , 0 )
global maxi
for i in range ( 0 , N + 1 ):
visited[i] = False
maxi = - 1
# To find end node of diameter
dfs1(startnode, 0 )
for i in range ( 0 , N + 1 ):
visited[i] = False
# x is the end node of diameter
x = endnode
vis[startnode] = True
# Mark all the nodes on diameter
# using back tracking
while x ! = startnode:
vis[x] = True
x = parent[x]
maxi = - 1
# Find the end node of longest
# branch to diameter
for i in range ( 1 , N + 1 ):
if vis[i]:
dfs2(i, 0 )
# Driver code if __name__ = = "__main__" :
N = 4
adjacent[ 1 ].append( 2 )
adjacent[ 2 ].append( 1 )
adjacent[ 1 ].append( 3 )
adjacent[ 3 ].append( 1 )
adjacent[ 1 ].append( 4 )
adjacent[ 4 ].append( 1 )
findNodes()
print ( "({}, {}, {})" . format (startnode, endnode, thirdnode))
# This code is contributed by Rituraj Jain |
// C# implementation of the approach using System;
using System.Collections.Generic;
class GFG {
static int MAX = 100005;
static List<List< int >> adjacent = new List<List< int >>();
static bool [] visited = new bool [MAX];
// To store the required nodes
static int startnode, endnode, thirdnode;
static int maxi = -1, N;
// Parent array to retrace the nodes
static int [] parent = new int [MAX];
// Visited array to prevent DFS
// in direction on Diameter path
static bool [] vis = new bool [MAX];
// DFS function to find the startnode
static void dfs( int u, int count)
{
visited[u] = true ;
int temp = 0;
for ( int i = 0; i < adjacent[u].Count; i++)
{
if (!visited[adjacent[u][i]])
{
temp++;
dfs(adjacent[u][i], count + 1);
}
}
if (temp == 0)
{
if (maxi < count)
{
maxi = count;
startnode = u;
}
}
}
// DFS function to find the endnode
// of diameter and maintain the parent array
static void dfs1( int u, int count)
{
visited[u] = true ;
int temp = 0;
for ( int i = 0; i < adjacent[u].Count; i++)
{
if (!visited[adjacent[u][i]])
{
temp++;
parent[adjacent[u][i]] = u;
dfs1(adjacent[u][i], count + 1);
}
}
if (temp == 0)
{
if (maxi < count)
{
maxi = count;
endnode = u;
}
}
}
// DFS function to find the end node
// of the Longest Branch to Diameter
static void dfs2( int u, int count)
{
visited[u] = true ;
int temp = 0;
for ( int i = 0; i < adjacent[u].Count; i++)
{
if (!visited[adjacent[u][i]] &&
!vis[adjacent[u][i]])
{
temp++;
dfs2(adjacent[u][i], count + 1);
}
}
if (temp == 0)
{
if (maxi < count)
{
maxi = count;
thirdnode = u;
}
}
}
// Function to find the required nodes
static void findNodes()
{
// To find start node of diameter
dfs(1, 0);
for ( int i = 0; i <= N; i++)
visited[i] = false ;
maxi = -1;
// To find end node of diameter
dfs1(startnode, 0);
for ( int i = 0; i <= N; i++)
visited[i] = false ;
// x is the end node of diameter
int x = endnode;
vis[startnode] = true ;
// Mark all the nodes on diameter
// using back tracking
while (x != startnode)
{
vis[x] = true ;
x = parent[x];
}
maxi = -1;
// Find the end node of longest
// branch to diameter
for ( int i = 1; i <= N; i++)
{
if (vis[i])
dfs2(i, 0);
}
}
static void Main() {
for ( int i = 0; i < MAX; i++)
adjacent.Add( new List< int >());
N = 4;
adjacent[1].Add(2);
adjacent[2].Add(1);
adjacent[1].Add(3);
adjacent[3].Add(1);
adjacent[1].Add(4);
adjacent[4].Add(1);
findNodes();
Console.WriteLine( "(" + startnode + ", " +
endnode + ", " +
thirdnode + ")" );
}
} // This code is contributed by divyeshrabadiya07. |
<script> // JavaScript implementation of the approach
let MAX = 100005;
let adjacent = [];
let visited = new Array(MAX);
// To store the required nodes
let startnode, endnode, thirdnode;
let maxi = -1, N;
// Parent array to retrace the nodes
let parent = new Array(MAX);
// Visited array to prevent DFS
// in direction on Diameter path
let vis = new Array(MAX);
// DFS function to find the startnode
function dfs(u, count)
{
visited[u] = true ;
let temp = 0;
for (let i = 0; i < adjacent[u].length; i++)
{
if (!visited[adjacent[u][i]])
{
temp++;
dfs(adjacent[u][i], count + 1);
}
}
if (temp == 0)
{
if (maxi < count)
{
maxi = count;
startnode = u;
}
}
}
// DFS function to find the endnode
// of diameter and maintain the parent array
function dfs1(u, count)
{
visited[u] = true ;
let temp = 0;
for (let i = 0; i < adjacent[u].length; i++)
{
if (!visited[adjacent[u][i]])
{
temp++;
parent[adjacent[u][i]] = u;
dfs1(adjacent[u][i], count + 1);
}
}
if (temp == 0)
{
if (maxi < count)
{
maxi = count;
endnode = u;
}
}
}
// DFS function to find the end node
// of the Longest Branch to Diameter
function dfs2(u, count)
{
visited[u] = true ;
let temp = 0;
for (let i = 0; i < adjacent[u].length; i++)
{
if (!visited[adjacent[u][i]] &&
!vis[adjacent[u][i]])
{
temp++;
dfs2(adjacent[u][i], count + 1);
}
}
if (temp == 0)
{
if (maxi < count)
{
maxi = count;
thirdnode = u;
}
}
}
// Function to find the required nodes
function findNodes()
{
// To find start node of diameter
dfs(1, 0);
for (let i = 0; i <= N; i++)
visited[i] = false ;
maxi = -1;
// To find end node of diameter
dfs1(startnode, 0);
for (let i = 0; i <= N; i++)
visited[i] = false ;
// x is the end node of diameter
let x = endnode;
vis[startnode] = true ;
// Mark all the nodes on diameter
// using back tracking
while (x != startnode)
{
vis[x] = true ;
x = parent[x];
}
maxi = -1;
// Find the end node of longest
// branch to diameter
for (let i = 1; i <= N; i++)
{
if (vis[i])
dfs2(i, 0);
}
}
for (let i = 0; i < MAX; i++)
adjacent.push([]);
N = 4;
adjacent[1].push(2);
adjacent[2].push(1);
adjacent[1].push(3);
adjacent[3].push(1);
adjacent[1].push(4);
adjacent[4].push(1);
findNodes();
document.write( "(" + startnode + ", " +
endnode + ", " +
thirdnode + ")" );
</script> |
(2, 3, 4)
Time Complexity: O(N+M) where N is the number of nodes in the graph and M is the number of edges in the graph.
Auxiliary Space: O(MAX)