Longest path in an undirected tree
Given an undirected tree, we need to find the longest path of this tree where a path is defined as a sequence of nodes.
Example:
Input : Below shown Tree using adjacency list
representation:
Output : 5
In below tree longest path is of length 5
from node 5 to node 7
This problem is the same as the diameter of the n-ary tree. We have discussed a simple solution here.
In this post, an efficient solution is discussed. We can find the longest path using two BFSs. The idea is based on the following fact: If we start BFS from any node x and find a node with the longest distance from x, it must be an endpoint of the longest path. It can be proved using contradiction. So our algorithm reduces to simple two BFSs. First BFS to find an endpoint of the longest path and second BFS from this endpoint to find the actual longest path.
For the proof of why does this algorithm works, there is a nice explanation here Proof of correctness: Algorithm for the diameter of a tree in graph theory
As we can see in the above diagram, if we start our BFS from node-0, the node at the farthest distance from it will be node-5, now if we start our BFS from node-5 the node at the farthest distance will be node-7, finally, the path from node-5 to node-7 will constitute our longest path.
Implementation:
C++
#include <bits/stdc++.h>
using namespace std;
class Graph
{
int V;
list< int > *adj;
public :
Graph( int V);
void addEdge( int v, int w);
void longestPathLength();
pair< int , int > bfs( int u);
};
Graph::Graph( int V)
{
this ->V = V;
adj = new list< int >[V];
}
void Graph::addEdge( int v, int w)
{
adj[v].push_back(w);
adj[w].push_back(v);
}
pair< int , int > Graph::bfs( int u)
{
int dis[V];
memset (dis, -1, sizeof (dis));
queue< int > q;
q.push(u);
dis[u] = 0;
while (!q.empty())
{
int t = q.front(); q.pop();
for ( auto it = adj[t].begin(); it != adj[t].end(); it++)
{
int v = *it;
if (dis[v] == -1)
{
q.push(v);
dis[v] = dis[t] + 1;
}
}
}
int maxDis = 0;
int nodeIdx;
for ( int i = 0; i < V; i++)
{
if (dis[i] > maxDis)
{
maxDis = dis[i];
nodeIdx = i;
}
}
return make_pair(nodeIdx, maxDis);
}
void Graph::longestPathLength()
{
pair< int , int > t1, t2;
t1 = bfs(0);
t2 = bfs(t1.first);
cout << "Longest path is from " << t1.first << " to "
<< t2.first << " of length " << t2.second;
}
int main()
{
Graph g(10);
g.addEdge(0, 1);
g.addEdge(1, 2);
g.addEdge(2, 3);
g.addEdge(2, 9);
g.addEdge(2, 4);
g.addEdge(4, 5);
g.addEdge(1, 6);
g.addEdge(6, 7);
g.addEdge(6, 8);
g.longestPathLength();
return 0;
}
|
Java
import java.util.Arrays;
import java.util.LinkedList;
import java.util.Queue;
class LongestPathUndirectedTree {
static class Pair<T,V> {
T first;
V second;
Pair(T first, V second) {
this .first = first;
this .second = second;
}
}
static class Graph {
int V;
LinkedList<Integer>[] adj;
Graph( int V) {
this .V = V;
adj = new LinkedList[V];
for ( int i = 0 ; i < V; ++i) {
adj[i] = new LinkedList<Integer>();
}
}
void addEdge( int s, int d) {
adj[s].add(d);
adj[d].add(s);
}
Pair<Integer, Integer> bfs( int u) {
int [] dis = new int [V];
Arrays.fill(dis, - 1 );
Queue<Integer> q = new LinkedList<>();
q.add(u);
dis[u] = 0 ;
while (!q.isEmpty()) {
int t = q.poll();
for ( int i = 0 ; i < adj[t].size(); ++i) {
int v = adj[t].get(i);
if (dis[v] == - 1 ) {
q.add(v);
dis[v] = dis[t] + 1 ;
}
}
}
int maxDis = 0 ;
int nodeIdx = 0 ;
for ( int i = 0 ; i < V; ++i) {
if (dis[i] > maxDis) {
maxDis = dis[i];
nodeIdx = i;
}
}
return new Pair<Integer, Integer>(nodeIdx, maxDis);
}
void longestPathLength() {
Pair<Integer, Integer> t1, t2;
t1 = bfs( 0 );
t2 = bfs(t1.first);
System.out.println( "Longest path is from " + t1.first
+ " to " + t2.first + " of length " +t2.second);
}
}
public static void main(String[] args){
Graph graph = new Graph( 10 );
graph.addEdge( 0 , 1 );
graph.addEdge( 1 , 2 );
graph.addEdge( 2 , 3 );
graph.addEdge( 2 , 9 );
graph.addEdge( 2 , 4 );
graph.addEdge( 4 , 5 );
graph.addEdge( 1 , 6 );
graph.addEdge( 6 , 7 );
graph.addEdge( 6 , 8 );
graph.longestPathLength();
}
}
|
C#
using System;
using System.Collections.Generic;
class GFG
{
public class Pair<T, V>
{
public T first;
public V second;
public Pair(T first, V second)
{
this .first = first;
this .second = second;
}
}
class Graph
{
int V;
List< int >[] adj;
public Graph( int V)
{
this .V = V;
adj = new List< int >[V];
for ( int i = 0; i < V; ++i)
{
adj[i] = new List< int >();
}
}
public void addEdge( int s, int d)
{
adj[s].Add(d);
adj[d].Add(s);
}
public Pair< int , int > bfs( int u)
{
int [] dis = new int [V];
for ( int i = 0; i < V; i++)
dis[i] = -1;
Queue< int > q = new Queue< int >();
q.Enqueue(u);
dis[u] = 0;
while (q.Count != 0)
{
int t = q.Dequeue();
for ( int i = 0; i < adj[t].Count; ++i)
{
int v = adj[t][i];
if (dis[v] == -1)
{
q.Enqueue(v);
dis[v] = dis[t] + 1;
}
}
}
int maxDis = 0;
int nodeIdx = 0;
for ( int i = 0; i < V; ++i)
{
if (dis[i] > maxDis)
{
maxDis = dis[i];
nodeIdx = i;
}
}
return new Pair< int , int >(nodeIdx, maxDis);
}
public void longestPathLength()
{
Pair< int , int > t1, t2;
t1 = bfs(0);
t2 = bfs(t1.first);
Console.WriteLine( "longest path is from " + t1.first +
" to " + t2.first + " of length " + t2.second);
}
}
public static void Main(String[] args)
{
Graph graph = new Graph(10);
graph.addEdge(0, 1);
graph.addEdge(1, 2);
graph.addEdge(2, 3);
graph.addEdge(2, 9);
graph.addEdge(2, 4);
graph.addEdge(4, 5);
graph.addEdge(1, 6);
graph.addEdge(6, 7);
graph.addEdge(6, 8);
graph.longestPathLength();
}
}
|
Python3
from collections import deque
class Graph:
def __init__( self , vertices):
self .vertices = vertices
self .adj = {i: [] for i in range ( self .vertices)}
def addEdge( self , u, v):
self .adj[u].append(v)
self .adj[v].append(u)
def BFS( self , u):
visited = [ False for i in range ( self .vertices + 1 )]
distance = [ - 1 for i in range ( self .vertices + 1 )]
distance[u] = 0
queue = deque()
queue.append(u)
visited[u] = True
while queue:
front = queue.popleft()
for i in self .adj[front]:
if not visited[i]:
visited[i] = True
distance[i] = distance[front] + 1
queue.append(i)
maxDis = 0
for i in range ( self .vertices):
if distance[i] > maxDis:
maxDis = distance[i]
nodeIdx = i
return nodeIdx, maxDis
def LongestPathLength( self ):
node, Dis = self .BFS( 0 )
node_2, LongDis = self .BFS(node)
print ( 'Longest path is from' , node, 'to' , node_2, 'of length' , LongDis)
G = Graph( 10 )
G.addEdge( 0 , 1 )
G.addEdge( 1 , 2 )
G.addEdge( 2 , 3 )
G.addEdge( 2 , 9 )
G.addEdge( 2 , 4 )
G.addEdge( 4 , 5 )
G.addEdge( 1 , 6 )
G.addEdge( 6 , 7 )
G.addEdge( 6 , 8 )
G.LongestPathLength()
|
Javascript
<script>
class Pair
{
constructor(first, second)
{
this .first = first;
this .second = second;
}
}
var V;
var adj;
function initialize(V)
{
this .V = V;
adj = Array.from(Array(V), ()=>Array());
}
function addEdge(s, d)
{
adj[s].push(d);
adj[d].push(s);
}
function bfs(u)
{
var dis = Array(V);
for ( var i = 0; i < V; i++)
dis[i] = -1;
var q = [];
q.push(u);
dis[u] = 0;
while (q.length != 0)
{
var t = q.shift();
for ( var i = 0; i < adj[t].length; ++i)
{
var v = adj[t][i];
if (dis[v] == -1)
{
q.push(v);
dis[v] = dis[t] + 1;
}
}
}
var maxDis = 0;
var nodeIdx = 0;
for ( var i = 0; i < V; ++i)
{
if (dis[i] > maxDis)
{
maxDis = dis[i];
nodeIdx = i;
}
}
return new Pair(nodeIdx, maxDis);
}
function longestPathLength()
{
var t1, t2;
t1 = bfs(0);
t2 = bfs(t1.first);
document.write( "longest path is from " + t1.first +
" to " + t2.first + " of length " + t2.second);
}
initialize(10)
addEdge(0, 1);
addEdge(1, 2);
addEdge(2, 3);
addEdge(2, 9);
addEdge(2, 4);
addEdge(4, 5);
addEdge(1, 6);
addEdge(6, 7);
addEdge(6, 8);
longestPathLength();
</script>
|
Output
Longest path is from 5 to 7 of length 5
Time Complexity: O(V+E) where V is the number of vertices and E is the number of edges.
Auxiliary Space: O(V+E)
Last Updated :
10 Mar, 2023
Like Article
Save Article
Share your thoughts in the comments
Please Login to comment...