Reputation:
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.
Upvotes: 8
Views: 22541
Reputation: 43477
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])
Upvotes: 6