洛谷 P1364医院设置 树形DP min型

题意:

有一棵树,树上不同的节点上居住着不同数量的鸟人,相邻节点边权距离都为1,现在要在树上某个节点的地方建一个鸟人院,使所有鸟人飞的路程和最小。

分析:
这个题目其实就是等同于求树的重心,然后我一开始想的是树的中心的升级版,他每个节点有不同的值,那还是用树的中心的思路,使用换根DP,

小小套用一下彩笔佬对换根DP的讲解:
换根DP 一般分为三个步骤:

1.指定任意一个根节点

2.一次dfs遍历,统计出当前子树内的节点对当前节点的贡献

3.一次dfs遍历,统计出当前节点的父节点对当前节点的贡献,然后合并统计

那在我们这边就是先用一次DFS求出将医院设在该节点时,所有子节点的居民到医院的路程之和(注意并不是所有节点的居民,只是以当前节点为根的子树的居民距离之和),以及当前子树的居民数量之和存储在cnt中。这样根节点的结果就是我们的初步结果。

然后从树根开始再进行一次DFS枚举医院的位置并求所有居民的路程之和,每次当医院从当前节点向子节点i移动时,以子节点i为根的居民到医院的距离会减少1,共减少cnt[i],其他节点的居民到医院的距离会增加1,共增加sum - cnt[i],这里sum是居民数量之和,因此总路程增加的量为sum - 2 * cnt[i],遍历完所有的节点并取最小值就是答案。

分析比较长,代码贴在下面

代码:

int dfs1(int u, int father) {
    int t = 0;
    for (int i = h[u]; ~i; i = ne[i]) {
        int j = e[i];
        if (j == father) continue;
        t += dfs1(j, u) + cnt[j];
        cnt[u] += cnt[j];
    }
    return t;
}
void dfs2(int u, int father, int cur) {
    res = min(res, cur);
    for (int i = h[u]; ~i; i = ne[i]) {
        int j = e[i];
        if (j == father) continue;
        dfs2(j, u, cur + sum - 2 * cnt[j]);
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值