定义
树的重心定义为,当把节点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;
}