洛谷P1131 【ZJOI2007】时态同步

题目传送门

这道题还是能比较容易的看出来它的树形结构的,时间即为边的长度,而且很显然的是,如果以 x x 为根的子树已经时态同步,那么以x的儿子为根的子树肯定也已经时态同步,也就是说我们可以从 x x 的儿子的状态推到x的状态,所以我们考虑树形DP。设 f[i] f [ i ] 表示在以 i i 为根的子树中达成时态同步需要最少用几次道具。

那么对于一个f[son[x]]已经全部计算完毕的节点 x x ,如何计算f[x]呢?要想让以 x x 为根的子树时态同步,需要将所有的叶节点到x的距离修改为这些距离里的最大值,也就是使用道具。所以我们需要记录这棵子树中叶节点到根的距离的最大值,并对其他子树进行修改(其实这一步不用真的写),同时更新 f[x] f [ x ] 。设以 i i 为根的子树里,所有叶节点中到根的最大距离是t[i] f[i]=t[i](t[j]+len[i,j])+f[j] f [ i ] = ∑ t [ i ] − ( t [ j ] + l e n [ i , j ] ) + f [ j ] j j i的儿子。

最后别忘了开 longlong l o n g l o n g

上代码

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
const int N=500000;
int n,rt,top,pre[(N<<1)+10],to[(N<<1)+10],len[(N<<1)+10],h[N+10];
long long f[N+10],t[N+10];
void ins(int u,int v,int w)
{
    pre[++top]=h[u];h[u]=top;to[top]=v;len[top]=w;
}
void dfs(int x,int fa)
{
    for(int i=h[x];i;i=pre[i])
    {
        int v=to[i];
        if(v==fa)continue;
        dfs(v,x);
        t[x]=max(t[x],t[v]+len[i]);
    }//计算t[x]
    for(int i=h[x];i;i=pre[i])
    {
        int v=to[i];
        if(v==fa)continue;
        f[x]+=f[v]+t[x]-t[v]-len[i];
    }//计算f[x]
}
int main()
{
    scanf("%d%d",&n,&rt);
    for(int i=1;i<n;i++)
    {
        int x,y,z;scanf("%d%d%d",&x,&y,&z);
        ins(x,y,z);ins(y,x,z);
    }
    dfs(rt,0);
    printf("%lld\n",f[rt]);return 0;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值