I am looking for an efficient algorithm. I would also appreciate a clean analysis of the same.
-
1Duplicate: http://stackoverflow.com/questions/4977112/how-to-find-the-shortest-simple-path-in-a-tree-in-a-linear-time/4977730#4977730 – IVlad Mar 07 '11 at 20:36
-
@SecureFish: Longest path or heaviest end-node? – oosterwal Mar 07 '11 at 20:44
-
@oosterwal, longest path. I think it means the summation of the weights of in the path is maximum among all. – SecureFish Mar 07 '11 at 21:21
-
Isn't computing longest path in a graph an NP-hard problem? – sc_ray Mar 08 '11 at 17:59
-
@sc_ray - Some graphs can be solved by negating all the edges. As long as there are no negative weight cycles in the resulting graph, it can be solved with a shortest path algorithm like Dijstrka. Since this a tree, there are no cycles – dfb Mar 08 '11 at 18:37
4 Answers
The answer is closely related to this question that appeared on SO last week. Instead of looking for a subsection of an array, you'll want to find the subsection of a tree.
I think it should be sufficient to start with the left-most end node and traverse your way up and down the tree towards the right-most end node keeping track of the largest path-sum and the current path-sum in the same way the solution in the linked question keeps track of the sums within an array.
I think BFS may be the right approach for this problem bcoz none of the branched paths will have a common node (This is obvious coz its a tree).
IDEA: During the return of the BFS at each step we can return the max length from the branching node to the children. But for the first call of BFS i.e for the root node we need to collect the max and second max path lengths, add them up this is the max distance required for the answer. If there are no multiple branches at the root node then the max distance is from the root node.
Code for the above algorithm:
int BFS(vertex V){
max_dist_to_children = INT_MIN;
// Here by parent i refer to the previous vertex
// through which V is explored (There will be only one parent, think!!)
for v in (neighbor(V) and v!=V.parent){
v.parent = V;
dist = BFS(v);
if dist > max_dist_to_children:
max_dist_to_children = dist;
}
return dist;
}
The first call of BFS from root node is a bit different from the above as the first call has to return the sum(max_distance, second_max_distance).

- 10,807
- 132
- 35
- 51

- 69
- 1
- 8
Without working off of any details, a simple DFS search should work
dfs( node, score ):
max = 0; maxv = None
for each edge in node
[val,path] = dfs( edge.child, edge.cost )
if(val>max)
max = val; maxv = path + [node]
return [max,maxv]
EDIT - Since there seems to be some confusion here, let me explain further. We can talk about 2 different problems, the first is that we consider this a tree interpreted as a DAG with a single root and a path starts at the root and takes a single path from that root. In this case, the function is called as dfs( root, 0 )
. In this case, are essentially building up a maximum cost for each node choosing either to
- A) Take one of the nodes as a path or
- B) Take no path, since all paths lead to a negative utility
The second problem is that the tree is not a DAG (proposed by Vlad) In this case we can start at any node and end at any node. Since there are no cycles in a tree, we can run an algorithm like Floyd-Warshall to find the longest path amongst all pairs.
Floyd-Warshall is roughly equivalent to memoziation of the routine above. If we add an additional parameter to keep track of the starting node, and try every starting node, paths will be reused. There may be a better way to exploit the structure of the tree, I'll think about that.
Example as proposed by Vlad (see comments for response)
*
1 / \ 1
* *
-1/
*

- 13,133
- 2
- 31
- 52
-
No it won't. You are only checking downward paths, but a path can go up then back down again too. – IVlad Mar 07 '11 at 22:51
-
-
@Voo - yes. Consider a node with two children. Go from the left child, to the parent and down to the right child. That's a perfectly valid path. – IVlad Mar 07 '11 at 23:22
-
@Vlad - the problem doesn't make sense if you can go up and down. The max path is simply the whole tree. Or am I missing something? – dfb Mar 07 '11 at 23:51
-
@Vlad - Additionally, if you're only allowing for simple (non-overlapping paths), you can just try every root. By memoizing the function above, it will take roughly the same time. – dfb Mar 07 '11 at 23:56
-
-
@osterwal - I don't see how this changes the algorithm. Did you have a counter example in mind? – dfb Mar 08 '11 at 02:22
-
@spinning_plate - the burden of proof lies on the person making the statement. When you make a statement that something works, you need to prove it, not ask others to tell you why it doesn't work. But fine. 1. I don't know what you mean with try every root, because paths do not have roots, and trying every path is certainly inefficient. 2. Consider a node with two children, all 3 with positive costs, whose left child has one children of its own, with negative cost. The max path is still a path that goes up and then back down again, yet isn't the whole tree. Sorry, but your algorithm is broken. – IVlad Mar 08 '11 at 08:41
-
@Vlad - See above. In the case of the single source problem, there is no issue with the negative weights. In your example, it would choose either the left or right node and not descend to the negative weight. In the all pairs problem - re 1) This is a tree. If the edges are undirected, any possible path that 'goes up' can be reinterpreted as a new 'tree' with the root at the start of the path. Finally, regarding your comments - I'm providing suggest ions towards a solution to a poorly defined problem and you're attacking me for asking for clarification on a comment - WTF? – dfb Mar 08 '11 at 18:30
-
@spinning_plate: I misread your code--it does account for negative edges. – oosterwal Mar 08 '11 at 18:33