Given an undirected connected tree with N nodes (and N-1 edges), we need to find two paths in this tree such that they are non-intersecting and the product of their length is maximum.

Examples:

Infirst treetwo paths which are non-intersecting and have highest product are, 1-2 and 3-4, so answer is 1*1 = 1 Insecond treetwo paths which are non-intersecting and has highest product are, 1-3-5 and 7-8-6-2 (or 4-8-6-2), so answer is 3*2 = 6

We can solve this problem by depth first search of tree by proceeding as follows, Since tree is connected and paths are non-intersecting, If we take any pair of such paths there must be a third path, connecting these two and If we remove an edge from the third path then tree will be divided into two components — one containing the first path, and the other containing the second path. This observation suggests us the algorithm: iterate over the edges; for each edge remove it, find the length of the path in both connected components and multiply the lengths of these paths. The length of the path in a tree can be found by modified depth first search where we will call for maximum path at each neighbor and we will add two maximum lengths returned, which will be the maximum path length at subtree rooted at current node.

Implementation Details:

Input is a tree, but there is no specified root in it as we have only collection of edges. The tree is represented as undirected graph. We traverse adjacency list. For every edge, we find maximum length paths on both sides of it (after removing the edge). We keep track of maximum product caused by an edge removal.

## C++

`// C++ program to find maximum product of two ` `// non-intersecting paths ` `#include <bits/stdc++.h> ` `using` `namespace` `std; ` ` ` `/* Returns maximum length path in subtree rooted ` ` ` `at u after removing edge connecting u and v */` `int` `dfs(vector<` `int` `> g[], ` `int` `& curMax, ` `int` `u, ` `int` `v) ` `{ ` ` ` `// To find lengths of first and second maximum ` ` ` `// in subtrees. currMax is to store overall ` ` ` `// maximum. ` ` ` `int` `max1 = 0, max2 = 0, total = 0; ` ` ` ` ` `// loop through all neighbors of u ` ` ` `for` `(` `int` `i = 0; i < g[u].size(); i++) ` ` ` `{ ` ` ` `// if neighbor is v, then skip it ` ` ` `if` `(g[u][i] == v) ` ` ` `continue` `; ` ` ` ` ` `// call recursively with current neighbor as root ` ` ` `total = max(total, dfs(g, curMax, g[u][i], u)); ` ` ` ` ` `// get max from one side and update ` ` ` `if` `(curMax > max1) ` ` ` `{ ` ` ` `max2 = max1; ` ` ` `max1 = curMax; ` ` ` `} ` ` ` `else` ` ` `max2 = max(max2, curMax); ` ` ` `} ` ` ` ` ` `// store total length by adding max ` ` ` `// and second max ` ` ` `total = max(total, max1 + max2); ` ` ` ` ` `// update current max by adding 1, i.e. ` ` ` `// current node is included ` ` ` `curMax = max1 + 1; ` ` ` `return` `total; ` `} ` ` ` `// method returns maximum product of length of ` `// two non-intersecting paths ` `int` `maxProductOfTwoPaths(vector<` `int` `> g[], ` `int` `N) ` `{ ` ` ` `int` `res = INT_MIN; ` ` ` `int` `path1, path2; ` ` ` ` ` `// one by one removing all edges and calling ` ` ` `// dfs on both subtrees ` ` ` `for` `(` `int` `i = 0; i < N; i++) ` ` ` `{ ` ` ` `for` `(` `int` `j = 0; j < g[i].size(); j++) ` ` ` `{ ` ` ` `// calling dfs on subtree rooted at ` ` ` `// g[i][j], excluding edge from g[i][j] ` ` ` `// to i. ` ` ` `int` `curMax = 0; ` ` ` `path1 = dfs(g, curMax, g[i][j], i); ` ` ` ` ` `// calling dfs on subtree rooted at ` ` ` `// i, edge from i to g[i][j] ` ` ` `curMax = 0; ` ` ` `path2 = dfs(g, curMax, i, g[i][j]); ` ` ` ` ` `res = max(res, path1 * path2); ` ` ` `} ` ` ` `} ` ` ` `return` `res; ` `} ` ` ` `// Utility function to add an undirected edge (u,v) ` `void` `addEdge(vector<` `int` `> g[], ` `int` `u, ` `int` `v) ` `{ ` ` ` `g[u].push_back(v); ` ` ` `g[v].push_back(u); ` `} ` ` ` `// Driver code to test above methods ` `int` `main() ` `{ ` ` ` `int` `edges[][2] = {{1, 8}, {2, 6}, {3, 1}, ` ` ` `{5, 3}, {7, 8}, {8, 4}, ` ` ` `{8, 6} }; ` ` ` `int` `N = ` `sizeof` `(edges)/` `sizeof` `(edges[0]); ` ` ` ` ` `// there are N edges, so +1 for nodes and +1 ` ` ` `// for 1-based indexing ` ` ` `vector<` `int` `> g[N + 2]; ` ` ` `for` `(` `int` `i = 0; i < N; i++) ` ` ` `addEdge(g, edges[i][0], edges[i][1]); ` ` ` ` ` `cout << maxProductOfTwoPaths(g, N) << endl; ` ` ` `return` `0; ` `} ` |

*chevron_right*

*filter_none*

## Python3

`# Python program to find maximum product of two ` `# non-intersecting paths ` ` ` `# Returns maximum length path in subtree rooted ` `# at u after removing edge connecting u and v ` `def` `dfs(g, curMax, u, v): ` ` ` ` ` `# To find lengths of first and second maximum ` ` ` `# in subtrees. currMax is to store overall ` ` ` `# maximum. ` ` ` `max1 ` `=` `0` ` ` `max2 ` `=` `0` ` ` `total ` `=` `0` ` ` ` ` `# loop through all neighbors of u ` ` ` `for` `i ` `in` `range` `(` `len` `(g[u])): ` ` ` ` ` `# if neighbor is v, then skip it ` ` ` `if` `(g[u][i] ` `=` `=` `v): ` ` ` `continue` ` ` ` ` `# call recursively with current neighbor as root ` ` ` `total ` `=` `max` `(total, dfs(g, curMax, g[u][i], u)) ` ` ` ` ` `# get max from one side and update ` ` ` `if` `(curMax[` `0` `] > max1): ` ` ` `max2 ` `=` `max1 ` ` ` `max1 ` `=` `curMax[` `0` `] ` ` ` `else` `: ` ` ` `max2 ` `=` `max` `(max2, curMax[` `0` `]) ` ` ` ` ` `# store total length by adding max ` ` ` `# and second max ` ` ` `total ` `=` `max` `(total, max1 ` `+` `max2) ` ` ` ` ` `# update current max by adding 1, i.e. ` ` ` `# current node is included ` ` ` `curMax[` `0` `] ` `=` `max1 ` `+` `1` ` ` `return` `total ` ` ` `# method returns maximum product of length of ` `# two non-intersecting paths ` `def` `maxProductOfTwoPaths(g, N): ` ` ` `res ` `=` `-` `999999999999` ` ` `path1, path2 ` `=` `None` `, ` `None` ` ` ` ` `# one by one removing all edges and calling ` ` ` `# dfs on both subtrees ` ` ` `for` `i ` `in` `range` `(N): ` ` ` `for` `j ` `in` `range` `(` `len` `(g[i])): ` ` ` ` ` `# calling dfs on subtree rooted at ` ` ` `# g[i][j], excluding edge from g[i][j] ` ` ` `# to i. ` ` ` `curMax ` `=` `[` `0` `] ` ` ` `path1 ` `=` `dfs(g, curMax, g[i][j], i) ` ` ` ` ` `# calling dfs on subtree rooted at ` ` ` `# i, edge from i to g[i][j] ` ` ` `curMax ` `=` `[` `0` `] ` ` ` `path2 ` `=` `dfs(g, curMax, i, g[i][j]) ` ` ` ` ` `res ` `=` `max` `(res, path1 ` `*` `path2) ` ` ` `return` `res ` ` ` `# Utility function to add an undirected edge (u,v) ` `def` `addEdge(g, u, v): ` ` ` `g[u].append(v) ` ` ` `g[v].append(u) ` ` ` `# Driver code ` `if` `__name__ ` `=` `=` `'__main__'` `: ` ` ` `edges ` `=` `[[` `1` `, ` `8` `], [` `2` `, ` `6` `], [` `3` `, ` `1` `], [` `5` `, ` `3` `], [` `7` `, ` `8` `], [` `8` `, ` `4` `], [` `8` `, ` `6` `]] ` ` ` `N ` `=` `len` `(edges) ` ` ` ` ` `# there are N edges, so +1 for nodes and +1 ` ` ` `# for 1-based indexing ` ` ` `g ` `=` `[[] ` `for` `i ` `in` `range` `(N ` `+` `2` `)] ` ` ` `for` `i ` `in` `range` `(N): ` ` ` `addEdge(g, edges[i][` `0` `], edges[i][` `1` `]) ` ` ` `print` `(maxProductOfTwoPaths(g, N)) ` ` ` `# This code is contributed by PranchalK ` |

*chevron_right*

*filter_none*

**Output:**

6

This article is contributed by **Utkarsh Trivedi**. 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 write comments if you find anything incorrect, or you want to share more information about the topic discussed above.

Attention reader! Don’t stop learning now. Get hold of all the important DSA concepts with the **DSA Self Paced Course** at a student-friendly price and become industry ready.

## Recommended Posts:

- Find maximum number of edge disjoint paths between two vertices
- Number of unique paths in tree such that every path has a value greater than K
- Count of all possible Paths in a Tree such that Node X does not appear before Node Y
- Count number of times each Edge appears in all possible paths of a given Tree
- Queries to find the count of shortest paths in a Tree that contains a given edge
- Count all possible paths between two vertices
- Number of Unicolored Paths between two nodes
- Check if given path between two nodes of a graph represents a shortest paths
- Maximum weighted edge in path between two nodes in an N-ary tree using binary lifting
- Count of Root to Leaf Paths consisting of at most M consecutive Nodes having value K
- Johnson's algorithm for All-pairs shortest paths
- Print all paths from a given source to a destination
- Printing Paths in Dijkstra's Shortest Path Algorithm
- Print all paths from a given source to a destination using BFS
- Paths to travel each nodes using each edge (Seven Bridges of Königsberg)
- Number of shortest paths in an unweighted and directed graph
- Johnson’s algorithm for All-pairs shortest paths | Implementation
- Unique paths covering every non-obstacle block exactly once in a grid
- Shortest paths from all vertices to a destination
- Check whether the cost of going from any node to any other node via all possible paths is same