【问题标题】:Deleting an edge from a tree to minimise the cost从树中删除一条边以最小化成本
【发布时间】:2022-01-05 10:00:46
【问题描述】:

让我们有一棵树,它的边缘由价格来衡量,价格是一些整数。我们将所有边的价格总和称为树的价格。如果我们通过删除一条边来切割一棵树,它将分成两棵树。我们称之为降价的最高价格。我们的任务是找到最便宜的切割。

输出应该是一个数字,即切割的最低价格。

例子:

输入:

5
1 4 1
1 2 1
2 3 3
4 5 2

第一个数字是顶点的数量。 之后,我们有顶点数 - 1 行。 行中的前两个数字是顶点之间的连接,所以1 4 表示1 和4 是连接的。行中的最后一个数字是边的“价格”。

所以在这种情况下,输出应该是 3,因为如果我们删除 2 和 1 之间的边,我们将得到两个子树,边分别是 3 和 3(它们的价格)。

  1
 /  \
2    4       
 \3   \2
  3    5

(图中/\是边,数字是顶点,/\旁边的数字是边的价格)

我考虑了一段时间,但不知道执行此操作的正确算法。

我写的基本程序:

number_of_vertices = int(input())
edges = []
price = []
for i in range(number_of_vertices):
    u, v, c = input().split()
    edges.append([int(u),int(v)])
    price.append(int(c))

我想过遍历每一条边,删除它们然后计算,但我不知道如何实现。

所以我制作了一个邻居字典和一个 find_path 算法来查找两个顶点之间是否存在边:

from collections import defaultdict

def find_path(graph, start, end, path=[]):
        path = path + [start]
        if start == end:
            return True
        if start not in graph:
            return False
        for node in graph[start]:
            if node not in path:
                newpath = find_path(graph, node, end, path)
                if newpath: return True
        return False

number_of_vertices = int(input())
edges = []
price = []
for i in range(number_of_vertices - 1):
    u, v, c = input().split()
    edges.append([int(u),int(v)])
    price.append(int(c))
   
graph = defaultdict(set)
for vertices in edges:
    graph[vertices[0]].add(vertices[1])
    graph[vertices[1]].add(vertices[0])
print(find_path(graph, 1, 3)) #this is just to make sure it works      
print(dict(graph)) #this too

【问题讨论】:

  • 你能否改写句子:“我必须找到边,如果我删除它,我计算剩余两棵树的边,较大的'价格'是最小的我可以通过切出一条边来实现。”
  • 对短语进行了一些更正
  • “我想过遍历每一条边,删除它们然后计算,但我不知道如何实现。” 那将是一个好地方开始。您需要能够检测到已删除边缘的两个组件。这实际上很简单:只需从已删除边的两个节点中的每一个开始遍历图(广度优先搜索或深度优先搜索,无关紧要)。
  • “我必须找到边缘,如果我删除它,我计算剩余两棵树的边缘,较大的“价格”是我可以通过切掉一个边缘。” 没有歧义地理解这句话仍然有点困难。我假设你想最小化两棵树的最大价格,但我不完全确定。
  • 那么,第 1 步:您能否实现从给定节点开始遍历图?

标签: python algorithm sorting


【解决方案1】:

首先,计算树的总价,假设为totalCost。现在我们将遍历这棵树并尝试删除每条边,看看砍价是否最低。

对于每个节点,我们可以计算其子树的价格。如果我们删除一个子树的边并且我们知道它的子树的成本,那么我们可以通过减去我们要删除的子树的价格和边成本来轻松找到剩余树的成本。假设我们正在删除UV 的边,成本为X,子树的成本VcostOfSubTree。那么剩下的树的成本是

costOfRemainingTree = totalCost - costOfSubTree - X

现在我们有了从 U 到 V 移除边后两棵树的成本。现在我们有最大的成本(切割价格)并将其与我们目前找到的最小切割进行比较。

这里的总成本是 21。子树 2 的成本是 12。现在如果我们从 1-2 中删除边,我们将有两棵树。一棵是成本为 12 的子树 2,另一棵树的成本是 (21 - 12 - 4) = 5,这里 4 是 1 - 2 的边成本。现在我们有两棵成本为 5 和 12 的树,所以这里是 Cut费用为 12。

通过这种方式,我们可以尝试每一条边,并尽量减少答案。如果我们知道要删除哪条边,我们就可以轻松找到两棵树的节点。

【讨论】:

    【解决方案2】:
    LOOP over nodes
      Calculate cost of subtree from node
    LOOP over links
      Calculate cut cost of link max( subtree cost of deepest node, tree cost - subtree cost - link cost )
      If cut cost less than previous cheapest, replace cheapest
    Output cheapest found
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-09-27
      • 2021-12-14
      • 1970-01-01
      • 2023-04-09
      • 1970-01-01
      • 1970-01-01
      • 2017-08-26
      • 1970-01-01
      相关资源
      最近更新 更多