题目: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; }