Tuesday, November 29, 2016

PT07Z-Longest path in a tree - SPOJ Problem 1437

Related: LeetCode 543 - Diameter of a Binary Tree
http://www.geeksforgeeks.org/diameter-of-a-binary-tree/
The diameter of a tree (sometimes called the width) is the number of nodes on the longest path between two leaves in the tree. The diagram below shows two trees each with diameter nine, the leaves that form the ends of a longest path are shaded (note that there is more than one path in each tree of length nine, but no path longer than nine nodes).
The diameter of a tree T is the largest of the following quantities:
* the diameter of T’s left subtree
* the diameter of T’s right subtree
* the longest path between leaves that goes through the root of T (this can be computed from the heights of the subtrees of T)
Optimized implementation: The above implementation can be optimized by calculating the height in the same recursion rather than calling a height() separately. Thanks to Amar for suggesting this optimized version. This optimization reduces time complexity to  O(n)

`class` `Height`
`{`
`    ``int` `h;`
`}`
`    ``/* define height =0 globally and  call diameterOpt(root,height)`
`       ``from main */`
`    ``int` `diameterOpt(Node root, Height height)`
`    ``{`
`        ``/* lh --> Height of left subtree`
`           ``rh --> Height of right subtree */`
`        ``Height lh = ``new` `Height(), rh = ``new` `Height();`
`        ``if` `(root == ``null``)`
`        ``{`
`            ``height.h = ``0``;`
`            ``return` `0``; ``/* diameter is also 0 */`
`        ``}`
`        `
`        ``/* ldiameter  --> diameter of left subtree`
`           ``rdiameter  --> Diameter of right subtree */`
`        ``/* Get the heights of left and right subtrees in lh and rh`
`         ``And store the returned values in ldiameter and ldiameter */`
`        ``lh.h++;     rh.h++; `
`        ``int` `ldiameter = diameterOpt(root.left, lh);`
`        ``int` `rdiameter = diameterOpt(root.right, rh);`
`        ``/* Height of current node is max of heights of left and`
`         ``right subtrees plus 1*/`
`        ``height.h = Math.max(lh.h, rh.h) + ``1``;`
`        ``return` `Math.max(lh.h + rh.h + ``1``, Math.max(ldiameter, rdiameter));`
`    ``}`
`    ``/* A wrapper over diameter(Node root) */`
`    ``int` `diameter()`
`    ``{`
`        ``Height height = ``new` `Height();`
`        ``return` `diameterOpt(root, height);`
`    ``}`

Time Complexity: O(n^2)
`    ``/* Method to calculate the diameter and return it to main */`
`    ``int` `diameter(Node root)`
`    ``{`
`        ``/* base case if tree is empty */`
`        ``if` `(root == ``null``)`
`            ``return` `0``;`
`        ``/* get the height of left and right sub trees */`
`        ``int` `lheight = height(root.left);`
`        ``int` `rheight = height(root.right);`
`        ``/* get the diameter of left and right subtrees */`
`        ``int` `ldiameter = diameter(root.left);`
`        ``int` `rdiameter = diameter(root.right);`
`        ``/* Return max of following three`
`          ``1) Diameter of left subtree`
`         ``2) Diameter of right subtree`
`         ``3) Height of left subtree + height of right subtree + 1 */`
`        ``return` `Math.max(lheight + rheight + ``1``,`
`                        ``Math.max(ldiameter, rdiameter));`
`    ``}`
`    ``/* A wrapper over diameter(Node root) */`
`    ``int` `diameter()`
`    ``{`
`        ``return` `diameter(root);`
`    ``}`
`    ``/*The function Compute the "height" of a tree. Height is the`
`      ``number f nodes along the longest path from the root node`
`      ``down to the farthest leaf node.*/`
`    ``static` `int` `height(Node node)`
`    ``{`
`        ``/* base case tree is empty */`
`        ``if` `(node == ``null``)`
`            ``return` `0``;`
`        ``/* If tree is not empty then height = 1 + max of left`
`           ``height and right heights */`
`        ``return` `(``1` `+ Math.max(height(node.left), height(node.right)));`
`    ``}`

http://www.spoj.com/problems/PT07Z/
You are given an unweighted, undirected tree. Write a program to output the length of the longest path (from one node to another) in that tree. The length of a path in this case is number of edges we traverse from source to destination.

Input

The first line of the input file contains one integer N --- number of nodes in the tree (0 < N <= 10000). Next N-1 lines contain N-1 edges of that tree --- Each line contains a pair (uv) means there is an edge between node u and node v (1 <= uv <= N).

Output

Print the length of the longest path on one line.

Example

```Input:
3
1 2
2 3

Output:
2```
http://www.fitcoding.com/2014/09/29/find-longest-path-in-tree/
```   public static int findLongestPath(TreeNode root)
{
// longest path = max (h1 + h2 + 2, longestpath(left), longestpath(right);

int[] treeInfo = longestPathHelper(root);

return treeInfo[0];
}

private static int[] longestPathHelper(TreeNode root)
{
int[] retVal = new int[2];

if (root == null)
{
//height and longest path are 0
retVal[0] = 0;
retVal[1] = 0;
}

int[] leftInfo = longestPathHelper(root.getLeft());
int[] rightInfo = longestPathHelper(root.getRight());

retVal[0] = Math.max(leftInfo[1] + rightInfo[1] + 2, Math.max(leftInfo[0], rightInfo[0]));
retVal[1] = Math.max(leftInfo[1], rightInfo[1]) + 1;

return retVal;
}```

Given below code is for PTZ07Z spoj or Longest path in a tree spoj.

You can solve this using DFS of applying BFS twice.

For BFS twice
In first bfs you have to find maximum length of node from root then in second bfs consider that node as root and find maximum distance from that .That will be our answer.

1-> Using DFS.
1-> Using DFS.

```#include <bits/stdc++.h>
using namespace std;
#define MAX 100009
bool check[MAX]={false};
int total=0;
int dfs(vector<int> v[],int root)
{
int m,m1=-1,m2=-1;
check[root]=1;
for(int i=0;i<v[root].size();i++)
{
if(!check[v[root][i]]){
m = dfs(v,v[root][i]);
if(m>=m1)
{
m2= m1;
m1 = m;
}
else if(m>m2)
m2=m;
}
}
total = max(total , m1+m2+2);
return (m1 + 1);
}
int main()
{
int n,a,b;
cin>>n;
vector<int> v[n+9];
for(int i=0;i<n-1;i++){
scanf("%d%d",&a,&b);
v[a].push_back(b);
v[b].push_back(a);
}
dfs(v,1);
cout<<total<<endl;
}
```
1-> Using Double BFS .

```#include <bits/stdc++.h>
using namespace std;
#define MAXN 10000
vector < int > g[MAXN + 1];
int maxWt[MAXN + 1];
bool check[MAXN + 1];
void bfs(int n)
{
queue <pair<int, int> > q;
q.push(make_pair(n, 0));
while (!q.empty())
{
int root = q.front().first;
int wt = q.front().second;
check[root] = true;
for(int i = 0; i<g[root].size(); i++)
{
if (!check[g[root][i]])
{
q.push(make_pair(g[root][i], wt + 1));
}
}
maxWt[root] = wt;
q.pop();
}
}
int main()
{
int n,a,b;
cin>>n;
vector<pair<int,int> > v[n+9];
for(int i=0;i<n-1;i++)
{
cin>>a>>b;
g[a].push_back(b);
g[b].push_back(a);
}
bfs(1);
int maxRoot = 0;
for(int i = 1; i<= n; i++)
maxRoot = maxWt[maxRoot] < maxWt[i] ? i : maxRoot;
memset(maxWt, 0, sizeof(maxWt));
memset(check, 0, sizeof(check));
bfs(maxRoot);
maxRoot = 0;
for(int i = 1; i<= n; i++)
maxRoot = max(maxRoot, maxWt[i]);
cout<<maxRoot<<endl;
return 0;
}```
https://sukeesh.wordpress.com/2015/06/21/spoj-pt07z-longest-path-in-a-tree/
http://duecodes.blogspot.com/2016/08/spoj-longest-path-in-tree-solution.html

http://www.cnblogs.com/moris/p/4337088.html
Longest path in an undirected tree
http://www.geeksforgeeks.org/longest-path-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.
This problem is same as diameter of n-ary tree.

In this post, an efficient solution is discussed. We can find 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 end point of the longest path. It can be proved using contradiction. So our algorithm reduces to simple two BFSs. First BFS to find an end point of the longest path and second BFS from this end point to find the actual longest path.
As we can see in 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, path from node-5 to node-7 will constitute our longest path.
`pair<``int``, ``int``> Graph::bfs(``int` `u)`
`{`
`    ``//  mark all distance with -1`
`    ``int` `dis[V];`
`    ``memset``(dis, -1, ``sizeof``(dis));`

`    ``queue<``int``> q;`
`    ``q.push(u);`

`    ``//  distance of u from u will be 0`
`    ``dis[u] = 0;`

`    ``while` `(!q.empty())`
`    ``{`
`        ``int` `t = q.front();       q.pop();`

`        ``//  loop for all adjacent nodes of node-t`
`        ``for` `(``auto` `it = adj[t].begin(); it != adj[t].end(); it++)`
`        ``{`
`            ``int` `v = *it;`

`            ``// push node into queue only if`
`            ``// it is not visited already`
`            ``if` `(dis[v] == -1)`
`            ``{`
`                ``q.push(v);`

`                ``// make distance of v, one more`
`                ``// than distance of t`
`                ``dis[v] = dis[t] + 1;`
`            ``}`
`        ``}`
`    ``}`

`    ``int` `maxDis = 0;`
`    ``int` `nodeIdx;`

`    ``//  get farthest node distance and its index`
`    ``for` `(``int` `i = 0; i < V; i++)`
`    ``{`
`        ``if` `(dis[i] > maxDis)`
`        ``{`
`            ``maxDis = dis[i];`
`            ``nodeIdx = i;`
`        ``}`
`    ``}`
`    ``return` `make_pair(nodeIdx, maxDis);`
`}`

`//  method prints longest path of given tree`
`void` `Graph::longestPathLength()`
`{`
`    ``pair<``int``, ``int``> t1, t2;`

`    ``// first bfs to find one end point of`
`    ``// longest path`
`    ``t1 = bfs(0);`

`    ``//  second bfs to find actual longest path`
`    ``t2 = bfs(t1.first);`

`    ``cout << ``"Longest path is from "` `<< t1.first << ``" to "`
`         ``<< t2.first << ``" of length "` `<< t2.second;`
`}`