E34 树形DP 树的中心
视频链接:E34 树形DP 树的中心_哔哩哔哩_bilibili
#include <iostream> #include <cstring> #include <algorithm> #include <vector> using namespace std; const int N=20010; int n,a,b,c,ans=2e9; struct edge{int v,w;}; vector<edge> e[N]; int d1[N],d2[N],path[N],up[N]; void dfs(int x,int fa){ for(auto ed : e[x]){ int y=ed.v, z=ed.w; if(y==fa) continue; dfs(y, x); if(d1[y]+z>d1[x]) d2[x]=d1[x],d1[x]=d1[y]+z,path[x]=y; else if(d1[y]+z>d2[x]) d2[x]=d1[y]+z; } } void dfs2(int x,int fa){ for(auto ed : e[x]){ int y=ed.v, z=ed.w; if(y==fa) continue; if(y==path[x])up[y]=max(up[x],d2[x])+z; else up[y]=max(up[x],d1[x])+z; dfs2(y, x); } } int main(){ cin>>n; for(int i=1; i<n; i++){ cin>>a>>b>>c; e[a].push_back({b,c}); e[b].push_back({a,c}); } dfs(1, 0); dfs2(1, 0); for(int i=1; i<=n; i++) ans=min(ans,max(d1[i],up[i])); cout<<ans; }
Luogu P3478 [POI2008] STA-Station
sz[u]: u子树的节点数
f[v]: 以 v 为根时所有结点的深度之和
dfs 预处理,求出每颗子树的大小sz[i],以 1 号点为根时所有结点的深度之和 f[1]
dfs2 换根时,f[u]→f[v]
在 v 的子树上的结点深度都减少了1,即 -sz[v]
不在 v 的子树上的结点深度都增加了1,即 n-sz[v]
所以,f[v] = f[u]-sz[v]+n-sz[v] = f[u]+n-2*sz[v]
#include <iostream> #include <cstring> #include <algorithm> #include <vector> using namespace std; const int N=1e6+10; int n,u,v; vector<int> e[N]; long long sz[N],dep[N],f[N]; void dfs(int u,int fa){ dep[u]=dep[fa]+1; f[1]+=dep[u]; sz[u]=1; for(int v:e[u]){ if(v!=fa){ dfs(v,u); sz[u]+=sz[v]; } } } void dfs2(int u,int fa){ for(int v:e[u]){ if(v!=fa){ f[v]=f[u]+n-2*sz[v]; dfs2(v,u); } } } int main(){ scanf("%lld",&n); for(int i=1; i<=n-1; i++){ scanf("%d%d",&u,&v); e[u].push_back(v); e[v].push_back(u); } dfs(1,0); dfs2(1,0); long long ans=-1; int id; for(int i=1; i<=n; i++) if(f[i]>ans) ans=f[i], id=i; printf("%d\n",id); }