树形dp,水。不存在找不到答案的情况。当1.子节点中节点数最大的与2.所有节点减去当前节点加所有子节点和的数目都小于等于n/2时满足条件。
ps:邻接表双向存边,访问注意不能回头访问父节点。
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <cmath>
using namespace std;
typedef long long LL;
#define INF 1000000007
#define N 100005
int n;
struct Node{
int v;
Node *next;
}e[N], *head[N];
int mv[N], sum[N];
int ptr = 0;
void init(){
ptr = 0;
for(int i = 0; i <= n; i++){
head[i] = NULL;
mv[i] = 0;
sum[i] = 0;
}
}
void adde(int x, int y){
e[ptr].v = x;
e[ptr].next = head[y];
head[y] = &e[ptr ++];
e[ptr].v = y;
e[ptr].next = head[x];
head[x] = &e[ptr ++];
}
int tdp(int x, int par){
Node *p = head[x];
while(p){
if(p -> v != par){//不能访问父节点
int vv = tdp(p -> v, x);
sum[x] += vv;
if(vv > mv[x])mv[x] = vv;
}
p = p -> next;
}
return sum[x] + 1;
}
int main(){
while(scanf("%d", &n) != EOF){
int x, y;
init();
for(int i = 1; i < n; i++){
scanf("%d%d", &x, &y);
adde(x, y);
}
tdp(1, 0);
for(int i = 1; i <= n; i++){
if(mv[i] <= n / 2 && sum[i] + 1 >= n / 2)printf("%d\n", i);
}
}
return 0;
}