树加重节点
回答
我们将在每棵树叶开始的树上执行洪水填充算法,并在洪水填充期间发现的路径上运行maximum subsequence sum算法。这为每对叶子产生候选最大值;我们选择其中最大的一个作为我们的真实答案。这个解决方案需要O(n^2)个时间:有O(n)个叶子,我们做O(n)来做每个叶子上最大子序列和问题的填充版本,产生O(n^2)候选生产阶段的工作总量。然后,我们做O(n^2)工作,从我们生成的O(n^2)个候选中选择最大路径。
我将在Haskell中给出一个示例实现。一些进口的,你可以忽略大部分:
import Data.List
import Data.Monoid
为了简单起见,我们将代表我们的树为函数,给定一个节点,讲述了重量和邻居有什么可用。命名类型和术语时,我将使用w
作为权重,n
作为节点。
type Tree w n = n -> (w, [n])
这将是方便有一种方法来指代的路径,其重量:
type WeightedPath w n = (Sum w, [n])
在我们的路,我们将保留两项统计数据,即最大路径在当前结束节点,以及迄今为止我们所见过的最大路径。对于空树对应的“空白摘要”,我们也会有一个常量:没有路径和零权重。
data Summary w n = Summary
{ endingHere :: WeightedPath w n
, endingAnywhere :: WeightedPath w n
}
emptySummary :: Num w => Summary w n
emptySummary = Summary mempty mempty
我们需要一个洪水填充算法。这很简单,虽然它通过“初始摘要”进行参数化,并且可以通过一个额外的加权节点来扩展摘要;这是因为我们将使用洪水填充算法来查找所有树叶并找到候选路径。我们需要注意的一个诀窍是确保我们不会回溯;我们跟踪nPrevious
中的前一个节点(如果有)用于此目的。
flood :: Eq n => (w -> n -> s -> s) -> s -> Tree w n -> n -> [s]
flood extend summary t = go Nothing summary where
go nPrevious summary nCurrent = case maybe id delete nPrevious ns of
[] -> [summary']
ns -> ns >>= go (Just nCurrent) summary'
where
(w, ns) = t nCurrent
summary' = extend w nCurrent summary
例如,我们可以通过让我们的“摘要”成为我们看到的最后一个节点来找到所有的叶子。如果树是空的,我们把我们的双手厌恶:
findLeaves :: Eq n => Tree w n -> n -> [n]
findLeaves = flood (\w n s -> n) undefined
我们可以通过一个节点链接的算法扩展候选路径的总结:
extend :: (Num w, Ord w, Ord n) => w -> n -> Summary w n -> Summary w n
extend w n s = answer where
answer = s
{ endingHere = max (0, []) ((Sum w, [n]) <> endingHere s)
, endingAnywhere = max (endingHere answer) (endingAnywhere s)
}
此功能插槽分成我们的洪水填充算法很好地找到从特定节点开始候选路径:
findCandidates :: (Num w, Ord w, Ord n) => Tree w n -> n -> [Summary w n]
findCandidates t n = findLeaves t n >>= flood extend emptySummary t
顶级功能少了点洪水填充,并挑选最大的候选人。 (方法是任意的,因为他们在extend
。)
maximalPath :: (Num w, Ord w, Ord n) => Tree w n -> n -> WeightedPath w n
maximalPath t n = maximum . map endingAnywhere $ findCandidates t n
让我们来看看它运行。我们将定义一个非常简单的样本树:它是一个星形树,节点0
位于中心,节点1
到5
每个都连接到中心集线器。该中心的重量为-1
,叶子根据它们是哪个节点加权1
到5
。
sampleTree :: Tree Int Int
sampleTree 0 = (-1, [1..5])
sampleTree n = (n, [0])
在ghci中,我们可以发现,现在提供了一个树,树中的任何节点发现的最大路径:
> maximalPath sampleTree 0
(Sum {getSum = 8},[5,0,4])
...它说,最大的一笔是8
,它可以通过从外部节点5的路径行进到集线器节点0来实现,然后向外到节点4。
请详细说明你的答案。你能举一些更多的例子吗? :p –
@ A.S.H我很乐意。你想看什么样的例子? –
这个算法可以处理圣诞树*吗? (只是开玩笑) –
在树计算的每个节点:
1)与最大总和产生往复路径m该节点的任何后代到该节点。
2)具有最大和的路径可以在以该节点为根的子树中找到。
这些都可以使用在该节点的子节点处计算的值来计算。
如果(1)答案是在该节点处开始和停止的0长度路径,或者该节点处的值与任何孩子处的最大值(1)之和。
如果(2)答案是该节点的两个最大(1)值的和,减去该节点的值或来自任何孩子的最大(2)值。
您正在查找的值是根(2)的值,并且您可以添加额外的簿记来计算所涉及的路径。
这里的成本基本上是成本递归遍历树,当你从一个深度优先搜索返回做的大部分工作,所以我认为这是O(n)
- 1. 树视图节点重选
- 2. 将节点添加到树
- 3. CheckBox节点树
- 4. 树节点和树状
- 5. 崩溃时重置树节点
- 6. D3.js树自定义节点重叠
- 7. 重新排列GWT中的树节点
- 8. 用nHibernate加载一棵树重新查询叶节点
- 9. 将重复项添加到现有节点时Mx树失败
- 10. 仅在扩展节点时加载树节点
- 11. GWT树的工具提示:将节点添加到节点
- 12. 处理树节点
- 13. +登录树节点
- 14. 扩大树节点
- 15. 树节点名称
- 16. 树视图添加节点问题
- 17. 将节点添加到D3树v4
- 18. 添加节点到排序树商店
- 19. 树形网格中加载子节点
- 20. 将节点添加到树的函数
- 21. 在Python中向树添加子节点
- 22. 无法孩子添加到树节点
- 23. 将节点添加到Dojo树
- 24. 删除和添加节点到树
- 25. dijit树和焦点节点
- 26. 树视图树节点复制
- 27. B树中的节点数
- 28. B树中的节点数
- 29. 检查cocos2d的节点树
- 30. 禁用树视图节点
为了在此获得帮助网站你需要发布一些代码 – Maxqueue