Here is a problem from Algorithms book by Vazirani
The input to this problem is a tree T with integer weights on the edges. The weights may be negative,
zero, or positive. Give a linear time algorithm to find the shortest simple path in T. The length of a
path is the sum of the weights of the edges in the path. A path is simple if no vertex is repeated. Note
that the endpoints of the path are unconstrained.
HINT: This is very similar to the problem of finding the largest independent set in a tree.
How can I solve this problem in linear time?
Here is my algorithm but I'm wonder if it is linear time since it is nothing different than depth-first:
- Traverse tree (depth-first)
- Keep the indexes (nodes)
- add the values
- do (1) till the end of tree
- compare the sum and print the path and sum
this problem is similar this topic but there is no certain answer.
This problem is pretty much equivalent to the minimum sum subsequence problem, and can be solved in a similar manner by dynamic programming.
We will calculate the following arrays by using DF searches:
dw1[i] = minimum sum achievable by only using node i and its descendants.
pw1[i] = predecessor of node i in the path found for dw1[i].
dw2[i] = second minimum sum achevable by only using node i and its descendants,
a path that is edge-disjoint relative to the path found for dw1[i].
If you can calculate these, take min(dw1[k], dw1[k] + dw2[k])
over all k
. This is because your path will take one of these basic shapes:
k k
| or / \
| / \
|
All of which are covered by the sums we're taking.
Calculating dw1
Run a DFS from the root node. In the DFS, keep track of the current node and its father. At each node, assume its children are d1, d2, ... dk
. Then dw1[i] = min(min{dw1[d1] + cost[i, d1], dw1[d2] + cost[i, d2], ..., dw1[dk] + cost[i, dk]}, min{cost[i, dk]})
. Set dw1[i] = 0
for leaf nodes. Don't forget to update pw1[i]
with the selected predecessor.
Calculating dw2
Run a DFS from the root node. Do the same thing you did for dw1
, except when going from a node i
to one of its children k
, only update dw2[i]
if pw1[i] != k
. You call the function recursively for all children however. It would look something like this in pseudocode:
df(node, father)
dw2[node] = inf
for all children k of node
df(k, node)
if pw1[node] != k
dw2[node] = min(dw2[node], dw1[k] + cost[node, k], cost[node, k])