include<cstdio>
#include<vector>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=20100;
int n,father;
int siz[maxn];//siz保存每个节点的子树大小。
bool vist[maxn];
int CenterOfGravity=0x3f3f3f3f,minsum=-1;//minsum表示切掉重心后最大连通块的大小。
vector<int>G[maxn];
void DFS(int u,int x){//遍历到节点x,x的父亲是u。
siz[x]=1;
bool flag=true;
for(int i=0;i<G[x].size();i++){
int v=G[x][i];
if(!vist[v]){
vist[v]=true;
DFS(x,v);//访问子节点。
siz[x]+=siz[v];//回溯计算本节点的siz
if(siz[v]>n/2) flag=false;//判断节点x是不是重心。
}
}
if(n-siz[x]>n/2) flag=false;//判断节点x是不是重心。
if(flag && x<CenterOfGravity) CenterOfGravity=x,father=u;//这里写x<CenterOfGravity是因为本题中要求节点编号最小的重心。
}
void init(){
memset(vist,false,sizeof(vist));
memset(siz,0,sizeof(siz));
minsum=-1;
CenterOfGravity=0x3f3f3f3f;
for(int i=0;i<maxn;i++) G[i].clear();
}
int main(){
int T;
scanf("%d",&T);
while(T--){
scanf("%d",&n);
init();
for(int i=1;i<n;i++){
int u,v;
scanf("%d%d",&u,&v);
G[u].push_back(v);
G[v].push_back(u);
}
vist[1]=1;
DFS(-1,1);//任意选取节点作为根,根节点的父亲是-1。
for(int i=0;i<G[CenterOfGravity].size();i++)
if(G[CenterOfGravity][i]==father) minsum=max(minsum,n-siz[CenterOfGravity]);
else minsum=max(minsum,siz[G[CenterOfGravity][i]]);
printf("%d %d\n",CenterOfGravity,minsum);
}
return 0;
}
树的重心
最新推荐文章于 2022-05-19 15:31:29 发布