Analysis
题目大意是给出一棵无根树,求出一些点,去掉这些点后剩下的含结点数最大的连通块的结点数最小。先令树的根为1,令sons[i]为结点i为根的子树的结点数,那么去掉该点后剩下的含结点数最大的连通块的结点数ans[i]=max(n-sons[i],max(sons[j])(map[i,j]=true)),那么对树遍历一次即可求出答案。
Accepted Code
var
n,a,b,i,edgenum,min,tot:longint;
first,dt,next,k,ans,fa,sons,q:array[0..35000] of longint;
procedure work;
var
i,t,u,v,head,tail:longint;
begin
head:=0;
tail:=1;
q[1]:=1;
while head<tail do
begin
inc(head);
u:=q[head];
ans[u]:=0;
sons[u]:=1;
t:=first[u];
while t<>0 do
begin
v:=dt[t];
if v<>fa[u] then
begin
fa[v]:=u;
inc(tail);
q[tail]:=v;
end;
t:=next[t];
end;
end;
for i:=tail downto 1 do
begin
u:=q[i];
if ans[u]<n-sons[u] then
ans[u]:=n-sons[u];
v:=fa[u];
if v<>0 then
begin
sons[v]:=sons[v]+sons[u];
if ans[v]<sons[u] then
ans[v]:=sons[u];
end;
end;
end;
procedure addedge(a,b:longint);
begin
inc(edgenum);
dt[edgenum]:=b;
next[edgenum]:=first[a];
first[a]:=edgenum;
end;
begin
readln(n);
edgenum:=0;
fillchar(first,sizeof(first),0);
for i:=1 to n-1 do
begin
readln(a,b);
addedge(a,b);
addedge(b,a);
end;
fa[1]:=0;
work;
tot:=0;
min:=maxlongint;
for i:=1 to n do
begin
if min>ans[i] then
begin
min:=ans[i];
tot:=0;
end;
if min=ans[i] then
begin
inc(tot);
k[tot]:=i;
end;
end;
writeln(min,' ',tot);
for i:=1 to tot-1 do
write(k[i],' ');
writeln(k[tot]);
end.