📜  树的所有对之间的最小边权的乘积(1)

📅  最后修改于: 2023-12-03 14:55:38.667000             🧑  作者: Mango

树的所有对之间的最小边权的乘积

树的所有对之间的最小边权的乘积指的是,对于一棵树,找到所有节点对之间的距离的最小值,把这些最小距离相乘得到的结果。

解法

解决这个问题的方法通常是基于动态规划。我们可以定义一个双重循环的二维数组 $dp_{i,j}$,其中 $dp_{i,j}$ 表示节点 $i$ 到节点 $j$ 的最小距离。

根据树的性质,我们可以发现,对于每一个节点 $i$,可以把整个树分为两个部分:以 $i$ 为根的子树和不以 $i$ 为根的子树。于是,我们可以把问题分解为两个子问题:计算 $i$ 到 $j$ 的距离,或者 $i$ 到 $j$ 经过 $i$ 的祖先节点的距离。

于是,我们可以使用下面的状态转移方程来计算 $dp_{i,j}$:

$dp_{i,j} = \min{dp_{i,k} + dp_{k,j}} \quad (k \in \operatorname{lca}(i,j))$

其中,$\operatorname{lca}(i,j)$ 表示节点 $i$ 和节点 $j$ 的最近公共祖先节点集合。

代码实现

下面是 Python 实现代码的示例,使用了前缀和优化和 DFS 迭代实现。

def dfs(u, fa, d, f):
    f[u] = 1
    for v, w in d[u]:
        if v == fa:
            continue
        dfs(v, u, d, f)
        f[u] += f[v]
        f[u] %= mod
        f[u] += f[v] * (n - f[v])
        f[u] %= mod
        sumd[u] += sumd[v] + f[v] * w
        sumd[u] %= mod

n = int(input())
d = [list() for i in range(n + 1)]
sumd = [0] * (n + 1)
mod = 998244353

for i in range(1, n):
    u, v, w = map(int, input().split())
    d[u].append((v, w))
    d[v].append((u, w))

dfs(1, 0, d, sumd)
ans = 0
for i in range(2, n + 1):
    ans += sumd[i] * i
    ans %= mod

print(ans)
参考资料