洛谷 P1131 [ ZJOI 2007 ] 时态同步 —— 树形DP

题目:https://www.luogu.org/problemnew/show/P1131

记录 x 子树内同步的时间 f[x],同步所需代价 g[x];

直接转移即可,让该儿子子树与其它儿子同步,只需要在自己到儿子的那一条边上改动。

代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
int const maxn=5e5+5;
int n,st,hd[maxn],ct,to[maxn<<1],nxt[maxn<<1],w[maxn<<1];
ll f[maxn<<1],g[maxn<<1];
void add(int x,int y,int z){to[++ct]=y; nxt[ct]=hd[x]; w[ct]=z; hd[x]=ct;}
int rd()
{
    int ret=0,f=1; char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1; ch=getchar();}
    while(ch>='0'&&ch<='9')ret=(ret<<3)+(ret<<1)+ch-'0',ch=getchar();
    return ret;
}
void dfs(int x,int fa)
{
    ll mx=0;
    for(int i=hd[x],u;i;i=nxt[i])
    {
        if((u=to[i])==fa)continue;
        dfs(u,x); mx=max(mx,f[u]+w[i]);
    }
    f[x]=mx;
    for(int i=hd[x],u;i;i=nxt[i])
    {
        if((u=to[i])==fa)continue;
        g[x]+=g[u]+mx-(f[u]+w[i]);
    }
}
int main()
{
    n=rd(); st=rd();
    for(int i=1,x,y,z;i<n;i++)
    {
        x=rd(); y=rd(); z=rd();
        add(x,y,z); add(y,x,z);
    }
    dfs(st,0);
    printf("%lld
",g[st]);
    return 0;
}
原文地址:https://www.cnblogs.com/Zinn/p/9677458.html