E34 树形DP 树的中心
在树中,如果节点
u 作为根节点时,从
u 出发的最长链最短,那么称
u 为树的中心。
- 树的中心不一定唯一,但最多有 2 个,且这两个中心是相邻的。
- 树的中心一定位于树的直径上。
- 树上所有点到其最远点的路径一定交会于树的中心。
- 当树的中心为根节点时,其到达直径端点的两条链分别为最长链和次长链。
- 当通过在两棵树间连一条边以合并为一棵树时,连接两棵树的中心可以使新树的直径最小。
// 树的中心 树形DP O(n) #include<bits/stdc++.h> using namespace std; const int N=1000010; int n,son[N]; long long f[N],g[N],up[N],d[N],md=1e18; vector<pair<int,int>> e[N]; vector<int> v; void dfs(int u,int fa){ for(auto [v,w]:e[u]){ if(v==fa) continue; dfs(v,u); if(f[u]<f[v]+w) g[u]=f[u],f[u]=f[v]+w,son[u]=v; //f[u]:u下方的最长距离 else if(g[u]<f[v]+w) g[u]=f[v]+w; //g[u]:u下方的次长距离 } } void dfs2(int u,int fa){ for(auto [v,w]:e[u]){ if(v==fa) continue; if(v==son[u]) up[v]=max(up[u],g[u])+w; else up[v]=max(up[u],f[u])+w; //up[v]:v上方的最长距离 dfs2(v,u); } d[u]=max(up[u],f[u]); //d[u]:到u的最长距离 md=min(md,d[u]); //最长距离的最小值 } int main(){ ios::sync_with_stdio(0); cin>>n; for(int i=1,a,b,c;i<n;i++){ cin>>a>>b>>c; e[a].emplace_back(b,c); e[b].emplace_back(a,c); } dfs(1,0); dfs2(1,0); for(int i=1;i<=n;i++) if(d[i]==md) v.emplace_back(i); for(int i:v) cout<<i<<"\n"; }
浙公网安备 33010602011771号