【题解】求树的重心

    科技2022-07-14  129

    定义

    树的重心定义为,当把节点x去掉后,其最大子树的节点个数最少(或者说成最大连通块的节点数最少),那么节点x就是树的重心。 通俗的理解:这个点去掉后,剩下的联通块尽量平均

    算法:

    树上任选一结点 u u u 开始 DFS,沿路统计其所有子树的大小和以它为根的子树的大小,这样也就可以得到一个点所有子树的大小及的大小

    还有一个问题,如果这个点不是根节点,那么删掉后剩下的连通块不止有他的子树,还有他上面的部分,这部分可以由总结点减去他自己的子树大小得到

    我们知道一个性质:删除重心后所得的所有子树,节点数不超过原树的1/2,那么我们使用这个性质来判断一个点是否为重心即可

    代码:

    #include<cstdio> #include<iostream> #include<vector> using namespace std; const int MAXN=105; vector<int> g[MAXN]; int dp[MAXN]; bool vis[MAXN]; int ans[MAXN]; int len=0; int n; void dfs(int x,int to){ dp[x]=1; bool flag=true; for(int i=0;i<g[x].size();i++){ int y=g[x][i]; if(!vis[y]){ vis[y]=true; dfs(y,x); dp[x]+=dp[y]; if(dp[y]>n/2){ flag=false; } } } if(n-dp[x]>n/2){ flag=false; } if(flag){ ans[++len]=x; } } int main(){ scanf("%d",&n); for(int i=1;i<=n-1;i++){ int u,v; scanf("%d %d",&u,&v); g[u].push_back(v); g[v].push_back(u); } dfs(1,-1); printf("%d\n",len);//有多少个重心 for(int i=1;i<=len;i++){ printf("%d\n",ans[i]);//输出每一个重心 } return 0; }
    Processed: 0.012, SQL: 8