Open In App

Find triplet such that number of nodes connecting these triplets is maximum

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: 
 

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>

Output: 
(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)


Article Tags :