解释:
树的重心定义为树的某个节点,当去掉该节点后,树的各个连通分量中,节点数最多的连通分量其节点数达到最小值
思路
首先,我们得明白一个性质:
删除重心后所得的所有子树,节点数不超过原树的1/2; 这不是废话
通过这个性质,我们可以对重心进行求解
树上任选一点i,进行DFS,并统计该点所有子树的大小和以它为根的子树的大小,这样也就可以得到一个点所有子树的大小及的大小,如果它的大小大于了原树的一半,就说明它不是重心
还有一个问题,如果这个点不是根节点,那么删掉后剩下的连通块不止有他的子树,还有他上面的部分,这部分可以由原树所有节点减去他自己的子树大小得到
代码
#include<bits/stdc++.h>
using namespace std
;
const int MAXN
=105;
vector
<int> v
[MAXN
];
int dp
[MAXN
]={};
int cnt
[MAXN
]={};
int CNT
=0,n
;
bool f
[MAXN
]={};
void DP(int x
){
dp
[x
]=1;
bool flag
=1;
for(int i
=0;i
<v
[x
].size();i
++){
int y
=v
[x
][i
];
if(f
[y
])
continue;
f
[y
]=1;
DP(y
);
dp
[x
]+=dp
[y
];
if(dp
[y
]>n
/2){
flag
=0;
}
}
if(n
-dp
[x
]>n
/2){
flag
=0;
}
if(flag
){
cnt
[++CNT
]=x
;
}
}
int main(){
scanf("%d",&n
);
for(int i
=1;i
<n
;i
++){
int x
,y
;
scanf("%d%d",&x
,&y
);
v
[x
].push_back(y
);
v
[y
].push_back(x
);
}
f
[1]=1;
DP(1);
printf("%d\n",CNT
);
sort(cnt
+1,cnt
+CNT
+1);
for(int i
=1;i
<=CNT
;i
++){
printf("%d\n",cnt
[i
]);
}
return 0;
}