树的每对顶点之间的最大流量和
Posted
技术标签:
【中文标题】树的每对顶点之间的最大流量和【英文标题】:Sum of maximum flow between every pair of vertices of a tree 【发布时间】:2016-08-11 05:19:27 【问题描述】:给定一棵无向树,其顶点编号为 1 到 N,N
。每棵边树都有一定的容量。求所有可能的顶点对之间的最大流量之和。在任何两个顶点之间只有一种方式可以通过。
求所有可能的顶点对之间的最大流量之和。
例如:在具有 3 条边的给定树中 1 2 5
2 3 6
节点 1 和节点 2 之间的边,容量为 5,节点 2 和节点 3 之间的边,容量为 6。Output - 32
(1,2) = (2,1) = 5
(1,3) = (3,1) = 5
(2,3) = (3,2) = 6
因此输出为(5+5+6)*2 = 32
我的方法-
Sort
基于 edge_capacity 的边
虽然edge_list
是not empty
:删除最小容量的边
left
和right
上的节点数。对节点数进行 DFS
在答案中添加 (left_count
* right_count
* edge_capacity
)。
返回answer*2
。
时间复杂度为 O(n2)。此解决方案提供 TLE。 我们如何进一步降低时间复杂度? 我的代码-
def dfs(node):
count = 1
visited = set()
stack = [node]
while stack:
vertex = stack.pop()
if vertex not in visited:
visited.add(vertex)
stack.extend(set(nodes[vertex]) - visited)
return len(visited)
for _ in range(int(raw_input())): # Iterate for multiple test cases
MOD = 1000000007
edges = []
n = int(raw_input()) # number of vertices
nodes = [set() for _ in range(n)]
for __ in range(n-1): # read input for number of edges
edges.append(map(int, raw_input().split()))
nodes[edges[-1][0]-1].add(edges[-1][1]-1)
nodes[edges[-1][1]-1].add(edges[-1][0]-1)
edges[-1][0]-=1; edges[-1][1]-=1;
edges.sort(key=lambda x: x[2])
answer = 0
for i in range(len(edges)):
weight = edges[i][2]
x, y = edges[i][0], edges[i][1]
nodes[x].remove(y)
nodes[y].remove(x)
left_count = dfs(x)
right_count = dfs(y)
answer += ((left_count*right_count*weight)%MOD)
print (answer*2)%MOD
链接到原始问题- Spoj-Flow on Tree
更新
约束-
-
测试用例数 - 10
1 5(每个测试用例中的顶点数)
每条边的容量都是非负的,不超过 106。
所有测试用例的总顶点数将小于 5*105。
【问题讨论】:
【参考方案1】:与其每次运行两个新的 DFS 来计算子树大小,不如只运行一次更智能的 DFS,它会为每个边 uv 计算在删除边 uv 时形成的以 u 为根的子树中的节点数。 (请注意,您需要为 uv 和 vu 计算此值。)
有关以线性时间计算这些节点数的方法,请参阅this nice answer。
【讨论】:
【参考方案2】:这是基于Kruskal's algorithm 和Union Find 的另一种有趣的方法:
algorithm Kruskal(G) is
res := 0
size := v:1 for v in G.V
for each (u,v) in G.E ordered by weight(u,v) decreasing do
u' := FIND-SET(u)
v' := FIND-SET(v)
res += weight(u,v) * size[u'] * size[v']
w' := UNION(u', v')
size[w'] = size[u'] + size[v']
return res
通过首先组合大边,我们总是知道我们正在研究的新边是子树中最小的。
如果您的边已经按重量排序,则基本上是线性时间。
【讨论】:
【参考方案3】:想法是通过按降序对边进行排序并找到每个联合的路径数来使用 DSU。
更有趣、更难的版本出现在 Facebook Hackercup 2021 第 1 轮中,您必须在其中做同样的事情,但要断开每个边缘。问题链接:https://www.facebook.com/codingcompetitions/hacker-cup/2021/round-1/problems/C
【讨论】:
以上是关于树的每对顶点之间的最大流量和的主要内容,如果未能解决你的问题,请参考以下文章