E34 树形DP 树的中心

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

 

树的中心 - OI Wiki

在树中,如果节点 u 作为根节点时,从 u 出发的最长链最短,那么称 u 为树的中心

  • 树的中心不一定唯一,但最多有 2 个,且这两个中心是相邻的。
  • 树的中心一定位于树的直径上。
  • 树上所有点到其最远点的路径一定交会于树的中心。
  • 当树的中心为根节点时,其到达直径端点的两条链分别为最长链和次长链。
  • 当通过在两棵树间连一条边以合并为一棵树时,连接两棵树的中心可以使新树的直径最小。

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

// 树的中心 树形DP O(n)
#include<bits/stdc++.h>
using namespace std;

const int N=1000010;
int n,son[N];
long long d1[N],d2[N],up[N],d[N],mxd=1e18;
vector<pair<int,int>> e[N];
vector<int> v;

void dfs(int x,int fa){
  for(auto [y,w]:e[x]){
    if(y==fa) continue;
    dfs(y,x);
    if(d1[x]<d1[y]+w) d2[x]=d1[x],d1[x]=d1[y]+w,son[x]=y; //d1[x]:x下方的最长距离
    else if(d2[x]<d1[y]+w) d2[x]=d1[y]+w; //d2[x]:x下方的次长距离
  }
}
void dfs2(int x,int fa){
  for(auto [y,w]:e[x]){
    if(y==fa) continue;
    if(y==son[x]) up[y]=max(up[x],d2[x])+w;
    else up[y]=max(up[x],d1[x])+w; //up[y]:y上方的最长距离
    dfs2(y,x);
  }
  d[x]=max(up[x],d1[x]); //d[x]:到x的最长距离
  mxd=min(mxd,d[x]);     //最长距离的最小值
}
int main(){
  ios::sync_with_stdio(0); cin.tie(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]==mxd) v.emplace_back(i);
  for(int i:v) cout<<i<<"\n";
}

 

U261056 树的中心 - 洛谷

 

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