题意:给你一个无根树,让你找到树的重心,就是树的重心的裸题,现在说一下树的重心把,树的重心就是以树的重心为根得到一颗有根树,这颗树中,节点最多的那颗子树的节点数量最少。
思路:根据定义去写的话,我们先随便以一个点为根,自底向上的求出他的所有子树数量,之后遍历每一个点,找到子树节点值最大的最小的那个数就好了
#include <vector>
#include <stdio.h>
#include <iostream>
#include <string.h>
using namespace std;
const int maxn = 20000 + 10;
vector<int>G[maxn];
int Size[maxn] , p[maxn];
void dfs(int u, int fa)
{
Size[u] = 1;
p[u] = fa;
for(int i = 0 ; i < G[u].size() ; i++)
{
int v = G[u][i];
if(v == fa) continue;
dfs(v,u);
Size[u] += Size[v];
}
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int n , u , v;
scanf("%d",&n);
memset(Size,0,sizeof(Size));
for(int i = 0 ; i <= n ; i ++) G[i].clear();
for(int i = 0 ; i < n - 1 ; i++)
{
scanf("%d%d",&u,&v);
G[u].push_back(v);
G[v].push_back(u);
}
dfs(1,0);
int node = 0 , ans = maxn;
for(int u = 1 ; u <= n ; u++)
{
int MAX = n - Size[u]; //看这里,如果按照以1为根节,那么u的子树就是Size[u],那么现在以u为根节点,那么他儿子方向的节点数是Size[u] ,父亲方向的节点数其实是n-Size[u]
for(int i = 0 ; i < G[u].size() ; i++) // 遍历儿子方向的子树大小
{
int v = G[u][i];
if(p[u] == v) continue;
MAX = max(MAX,Size[v]);
}
if(MAX < ans)
{
ans = MAX;
node = u;
}
}
printf("%d %d\n",node,ans);
}
}