简体   繁体   中英

Is there an algorithm to find the minimum cost path in a directed rooted tree (arborescence)?

To be more specific : I have a rooted tree which represents the different paths of a matrix from its first element to its last, with only right, down and diagonal down movements allowed. Hence, every node can have up to 3 children. The tree will have the first element of the matrix as its root and every last node will be the last element of the matrix. Every node represents a cost.

Here's an example of what kind of tree I'm talking about : 在此处输入图片说明

Here the minimum cost path would be : 1 -> 2 -> 9 or [0,0,2] in "coordinates"

So is there any algorithm that is able to find the minimum cost path (I mean the path not the total cost of the minimum cost path) for this kind of tree ?
And if yes, is it possible to implement it in a recursive way ?

This can be done in O( n ) time, where n is the number of nodes. The solution is recursive:

  • The minimum cost path for a leaf node is trivial - it is just the node itself, with the node's own cost.

  • To find the minimum cost path for an internal node, make recursive calls on all its children, and select whichever child node has the lowest cost for its minimum cost path. The cost of the path equals the node's own cost plus the cost of the path for that child.

To recover the path, simply return both the cost and the path from the function. The recursive case has to extend the path with the current node.

The total running time is O( n ) because the non-recursive work done for an internal node is proportional to the number of children. The running time cannot be improved on asymptotically, but it could be optimised in practice using a branch-and-bound algorithm which keeps track of the lowest cost path so far, and rejecting paths which exceed it.


Here's an example in Python:

class Node:
    def __init__(self, cost, children=()):
        self.cost = cost
        self.children = children
    def __repr__(self):
        return 'Node({})'.format(self.cost)

root = Node(1, (
    Node(2, (
        Node(5, (Node(9),)),
        Node(6, (Node(9),)),
        Node(9),
    )),
    Node(3, (
        Node(8, (Node(9),)),
        Node(9),
    )),
    Node(4, (Node(9),)),
))

def min_cost_path(node):
    if not node.children:
        return [node], node.cost
    else:
        # list of (path, cost) pairs
        options = [min_cost_path(c) for c in node.children]
        path, cost = min(options, key=lambda option: option[1])
        path.append(node)
        return path, cost + node.cost

Example:

>>> path, cost = min_cost_path(root)
>>> path
[Node(9), Node(2), Node(1)]
>>> cost
12

Note that the path is returned in reverse order.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM