标签是树形dp,但其实没啥必要用dp。
显然数据给出的是树形结构,要求所有叶子节点到根节点路径长度相同,可以想到自下向上地进行维护。
首先从根节点dfs,找到叶子节点后向上回溯,先维护父节点的所有子节点到父节点最大边权。
然后维护ans,ans为最大边权减去所有到子节点的边权。因为边权只能增大不能减小,用时短的节点必须等待用时长的节点。
然后维护父节点的边权,父节点边权为该节点子节点的最大边权+父节点到该节点的时间。
继续回溯,重复操作,到根节点为止。
#include<cstdio> #include<cstring> #include<cstring> #include<cmath> #include<iostream> using namespace std; int n,head[500005],nxt[1000005],to[1000005],tot=0,maxn[500005],val[1000005]; long long ans; void add(int x,int y,int k) { nxt[++tot]=head[x]; head[x]=tot; to[tot]=y; val[tot]=k; } void dfs(int x,int fa) { for(int i=head[x];i;i=nxt[i]) { if(to[i]!=fa) dfs(to[i],x); } for(int i=head[x];i;i=nxt[i]) if(to[i]!=fa) maxn[x]=max(maxn[x],val[i]); for(int i=head[x];i;i=nxt[i]) if(to[i]!=fa) ans+=(maxn[x]-val[i]); for(int i=head[fa];i;i=nxt[i]) if(to[i]==x) val[i]+=maxn[x]; } int main() { cin>>n; int s; cin>>s; for(int i=1;i<n;i++) { int a,b,c; cin>>a>>b>>c; add(a,b,c); add(b,a,c); } dfs(s,0); cout<<ans; return 0; }
原文地址:https://www.cnblogs.com/charlesss/p/10340520.html
时间: 2024-10-03 05:26:07