树的重心
树的重心:找到一个点,其所有的子树中最大的子树节点数最少,那么这个点就是这棵树的重心,删去重心后,生成的多棵树尽可能平衡。使得以该节点为根的子树中,最大子树高度最小的节点
//会议 //https://www.luogu.com.cn/problem/P1395 // f数组:f数组用于记录以每个节点为根的子树中的最大深度(高度)。对于每个节点u,f[u]表示以u为根的子树的最大深度。 // g数组:g数组用于记录以每个节点为根的子树中,u的子节点(不包括u本身)到其他叶子节点的最大距离(即最长路径)。 // 对于每个节点u,g[u]表示以u为根的子树中,u的子节点到其他叶子节点的最大距离。 //树的重心:找到一个点,其所有的子树中最大的子树节点数最少,那么这个点就是这棵树的重心,删去重心后,生成的多棵树尽可能平衡。 //树的重心是使得以该节点为根的子树中,最大子树高度最小的节点 //根据重心定义, #include<bits/stdc++.h> using namespace std; const int N=1e5+10; int n,m,res,f[N],g[N],num,ans=2e9; int e[N],ne[N],h[N],idx; bool vis[N]; void add(int a,int b){ e[idx]=b,ne[idx]=h[a],h[a]=idx++; } void dfs(int u) { vis[u]=true; for(int i=h[u];~i;i=ne[i]){ int j=e[i]; if(!vis[j]){ dfs(j); g[u]+=g[j]+1; f[u]=max(f[u],g[j]+1); } } f[u]=max(f[u],n-g[u]-1); vis[u]=false; } int main() { cin>>n; memset(h, -1, sizeof h); for(int i=0;i<n-1;i++){ int a,b; cin>>a>>b; add(a,b),add(b,a); } dfs(1);//以任意一个节点开始,寻找树的重心 cout<<f[1]<<endl; for(int i=1;i<=n;i++) if(ans>f[i]) num=i,ans=f[i]; cout<<num<<" "; memset(g,0,sizeof(g)); dfs(num);//重置,搜索重心 for(int i=1;i<=n;i++) res+=g[i]; cout<<res<<endl; return 0; }