如果发现广告等破坏行为,请尽量将条目恢复到较早的版本而不是把相应内容直接删除,谢谢合作。

URAL/1056

来自"NOCOW"

跳转到: 导航, 搜索

Solution From Xcheng:

求树的中心。 树的中心的定义就是 到(最远的点的距离)最短的点。


方法一: 预处理每二个结点间的距离 然后找中心 O(n^3) 超时

方法二: BFS twice 第一次找离结点1最远的点K 再找离K最远的点X K~X就是最长链 链上的中点就是中心 O(n)

方法三: 第一次动规做f[i]:=max(f[son])+1,第二次动规做f[i]:=max(f[i],f[father] + 1) 。 但是存在一个问题就是如果f[father]的值是从i那里得到的,这样计算显然就错了。 不要放弃,在实际操作过程中,f需要记下两个值,一个是最优值,一个是次优值,这两个值必须由不用的子结点得到。这样当最优值发生矛盾的时候,次优值一定不会矛盾。问题就解决了。复杂度O(N)十分的理想。


看一眼就知道是树形DP,以随便一个节点(我的程序里是1)建树。

f1[i]表示以i为根的子树中,i到叶子节点的距离最大值;

f2[i]表示以i为根的子树中,i到叶子节点的距离次大值;

同时分别记录f1[i],f2[i]是从哪个子树更新来的

g[i]表示除了以i为根的子树中的叶子节点外,其他的叶子节点到i的最大值。

首先一遍树形Dp算出f1,f2。

设parent[v]=w

g[v]=max(f1[w],g[w])+1 当f1[w]不从v更新而来

g[v]=max(f2[w],g[w])+1 当f1[w]从v更新而来

最后输出f1和g中最大值即可。


program cao;
const
  maxn=12000;
 
type
  node=record
    v,next:longint;
  end;
 
var
  t:array[0..maxn] of node;
  head,f1,f2,g,ans,from1,from2,fa:array[0..maxn] of longint;
  a,b,c,d,e,h,i,j,k,l,n,m,p,q,total:longint;
 
procedure init;
begin
  read(n);
  for i:=2 to n do
  begin
    read(a);
    fa[i]:=a;
    inc(total);
    t[total].v:=i;
    t[total].next:=head[a];
    head[a]:=total;
  end;
end;
 
procedure update(dis,son,v:longint);
begin
  if dis>f1[v] then
  begin
    f2[v]:=f1[v];
    from2[v]:=from1[v];
    f1[v]:=dis;
    from1[v]:=son;
  end
  else
  if dis>f2[v] then
  begin
    f2[v]:=dis;
    from2[v]:=son;
  end;
end;
 
procedure search(v:longint);
var
  i:longint;
begin
  i:=head[v];
  while i<>0 do
  begin
    search(t[i].v);
    update(f1[t[i].v]+1,t[i].v,v);
    i:=t[i].next;
  end;
end;
 
procedure search2(v:longint);
var
  i:longint;
begin
  if from1[fa[v]]=v then g[v]:=f2[fa[v]]+1 else g[v]:=f1[fa[v]]+1;
  if g[fa[v]]+1>g[v] then g[v]:=g[fa[v]]+1;
  i:=head[v];
  while i<>0 do
  begin
    search2(t[i].v);
    i:=t[i].next;
  end;
end;
 
procedure main;
begin
  search(1);
  g[0]:=-1;
  f1[0]:=-1;
  f2[0]:=-1;
  search2(1);
  for i:=1 to n do
    if f1[i]>g[i] then ans[i]:=f1[i] else ans[i]:=g[i];
end;
 
procedure print;
begin
  p:=maxlongint;
  for i:=1 to n do
    if ans[i]<p then
    begin
      k:=i;
      p:=ans[i];
    end;
  for i:=1 to n do
    if ans[i]=p then write(i,‘ ‘);
  writeln;
end;
 
begin
  init;
  main;
  print;
end.
program ural1056;
const
  maxn=10000;
var
  pr,u,d1,d2,c1,cen:array[1..maxn]of word;
  n,i,min,count,t:word;
procedure submit(d,c,x:word);
  begin
    if d>d1[x] then begin
      d2[x]:=d1[x];d1[x]:=d;c1[x]:=c;
    end
    else if d>d2[x] then d2[x]:=d;
  end;
function max(a,b:word):word;
  begin
    if a>b then max:=a else max:=b;
  end;
begin
  read(n);
  for i:=2 to n do
    read(pr[i]);
 
  for i:=n downto 2 do
    submit(d1[i]+1,i,pr[i]);
 
  for i:=2 to n do begin
    if i=c1[pr[i]] then u[i]:=d2[pr[i]]+1 else u[i]:=d1[pr[i]]+1;
    if u[pr[i]]+1>u[i] then u[i]:=u[pr[i]]+1;
  end;
 
  min:=maxint;
  for i:=1 to n do begin
    t:=max(u[i],d1[i]);
    if t<min then begin min:=t;count:=0;end;
    if t=min then begin inc(count);cen[count]:=i;end;
  end;
 
  for i:=1 to count-1 do
    write(cen[i],' ');
  writeln(cen[count]);
end.
个人工具