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);
}

 

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