思路:设dp[i]为在i的子树中,删去i后的最大连通子图的顶点个数。
dp[u] = max(dp[u],num[v])。
代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std;
const int maxn = 50005;
const int INF = 1e6+5;
struct Nod{
int b,next;
void init(int b,int next){
this->b=b;this->next=next;
}
}buf[maxn<<1];
int len,E[maxn];
int n,num[maxn],dp[maxn];
void init(){
len=0;
memset(E,-1,sizeof(E));
memset(dp,0,sizeof(dp));
}
void add_edge(int a,int b){
buf[len].init(b,E[a]);E[a]=len++;
buf[len].init(a,E[b]);E[b]=len++;
}
void dfs(int u,int pre){
int i,v;
num[u] = 1;
for(i=E[u];i!=-1;i=buf[i].next){
v=buf[i].b;
if(v == pre) continue;
dfs(v,u);
num[u] += num[v];
dp[u] = max(dp[u],num[v]);
}
dp[u] = max(dp[u],n-num[u]);
}
int main(){
int i,j,a,b,o = INF;
init();
scanf("%d",&n);
for(i=1;i<n;i++){
scanf("%d%d",&a,&b);
add_edge(a,b);
}
dfs(1,-1);
for(i=1;i<=n;i++) o = min(o,dp[i]);
for(i=1,j=0;i<=n;i++){
if(o == dp[i]){
if(j) putchar(' ');j++;
printf("%d",i);
}
}
return 0;
}