在树中查找路径/子路径,使得权重总和小于给定的整数

时间:2017-10-14 15:56:36

标签: c++ algorithm graph tree

给定一个具有n个节点(从1到n编号)和n-1个边缘的树。每个边缘都有两个整数,一个与之相关的权重和增益。您还可以获得一个数字K.您可以从任何节点开始,您必须进行交易。在每笔交易中,您将失去等于边缘权重的金额,并获得等于边缘收益值的利润。您必须最大化利润,使总损失金额<= K

这是指原始问题的链接。相应的比赛现已结束。

https://www.hackerrank.com/contests/gs-quantify-2017/challenges/profit-maximization

我做了什么:

我通过将每个节点视为路径的起始节点,然后通过考虑遵守约束的每个后续节点递归计算最大利润来构建递归方法。

但很明显,这具有非常高的时间复杂性。

有更优雅,更省时的方法吗?

1 个答案:

答案 0 :(得分:0)

这是一个建议:

  1. 选择靠近图形中心的节点(例如,通过反复修剪所有叶节点并选择删除的最后一个节点)
  2. 如果解决方案使用该节点(不一定是起始节点 - 它可能只是在中间),计算出最佳利润。
  3. 如果解决方案依次使用每个子树(即不使用所选节点),则计算出最佳利润
  4. 要使用特定节点x计算解决方案的利润,您可以使用DFS计算到达每个节点的总重量和利润。

    然后为x的每个子子树:

    1. 构建从权重到利润的有序地图(此地图应按权重增加排序)
    2. 删除利润低于早期利润的任何条目(没有点保持权重更大但利润更少的路线)
    3. 然后,您可以合并这些子树,以查找包含x:

      的任何路线的最大利润
      1. 从子1的有序地图开始
      2. 通过地图为孩子1向前迭代,向后遍历孩子2的地图,以便从从孩子1开始到孩子2结束的路线中找到最高利润。
      3. 合并儿童1和儿童2的地图,然后重复儿童3,4,5 ......
      4. 请注意,步骤2和步骤3在合并的条目数中都是线性的。

        如果存在较高的分支因子,则此合并步骤可能会变得太慢,在这种情况下,您可以通过始终合并两个最小的子树而不是仅按顺序合并来提高效率。可以使用堆数据结构有效地告诉您哪两个最小。

        可能有一个更简单的解决方案,Hackerrank通常会在一段时间后发布社论,因此将来值得重新检查您的问题链接。