E32 树形DP 树的重心

E32 树形DP 树的重心_哔哩哔哩_bilibili

U104609 【模板】树的重心 - 洛谷

如果删除树中某个节点,使得各个子树的最大节点数最小,则该节点被称为树的重心

  • 树的重心如果不唯一,则至多有 2 个,且这两个重心相邻。
  • 以树的重心为根时,所有子树的大小都不超过整棵树大小的一半。
  • 树中所有点到某个点的距离和中,到重心的距离和是最小的;如果有两个重心,那么到它们的距离和一样。
  • 把两棵树通过一条边相连得到一棵新的树,那么新的树的重心在连接原来两棵树的重心的路径上。
  • 在一棵树上添加或删除一个叶子,那么它的重心最多只移动一条边的距离。
// 树的重心 树形DP O(n)
#include<bits/stdc++.h>
using namespace std;

const int N=50010;
int n,siz[N],f[N],cnt=1e9;
vector<int> e[N],g;

void dfs(int u,int fa){
  siz[u]=1;
  for(auto v:e[u]){
    if(v==fa) continue;
    dfs(v,u);
    f[u]=max(f[u],siz[v]); //u的最大子树
    siz[u]+=siz[v];
  }
  f[u]=max(f[u],n-siz[u]); //删除u后的最大连通块
  cnt=min(cnt,f[u]);       //最大块最小化
}
int main(){
  scanf("%d",&n);
  for(int i=1,a,b;i<n;i++){
    scanf("%d%d",&a,&b);
    e[a].push_back(b);
    e[b].push_back(a);
  }
  dfs(1,0); 
  for(int i=1;i<=n;i++) if(f[i]==cnt) g.push_back(i);
  for(int v:g) printf("%d ",v);
}

 

P1395 会议 - 洛谷

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

const int N=50010;
int n,siz[N],f[N],d[N],cnt=1e9,v,sum;
vector<int> e[N];

void dfs(int u,int fa){
  siz[u]=1;
  for(auto v:e[u]){
    if(v==fa) continue;
    dfs(v,u);
    f[u]=max(f[u],siz[v]); //u的最大子树
    siz[u]+=siz[v];
  }
  f[u]=max(f[u],n-siz[u]); //删除u后的最大连通块
  cnt=min(cnt,f[u]);       //最大块最小化
}
void dfs2(int u,int fa){
  for(auto v:e[u]){
    if(v==fa) continue;
    d[v]=d[u]+1;
    dfs2(v,u);
  }
  sum+=d[u];
}
int main(){
  scanf("%d",&n);
  for(int i=1,a,b;i<n;i++){
    scanf("%d%d",&a,&b);
    e[a].push_back(b);
    e[b].push_back(a);
  }
  dfs(1,0); 
  for(int i=1;i<=n;i++) if(f[i]==cnt){v=i;break;}
  dfs2(v,0);
  printf("%d %d",v,sum);
}

 

 

树的重心 - OI Wiki

P12007 【MX-X10-T3】[LSOT-4] 全国联赛? - 洛谷

CF685B Kay and Snowflake - 洛谷

1655 -- Balancing Act (poj.org)

 

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