E34 树形DP 树的中心

E34 树形DP 树的中心_哔哩哔哩_bilibili

U392706 【模板】树的中心 - 洛谷

在树中,如果节点 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";
}

 

树的中心 - OI Wiki

U261056 树的中心 - 洛谷

 

posted @ 2023-04-10 10:20  董晓  阅读(786)  评论(0)    收藏  举报