[BZOJ1131] [POI2008]Sta

传送门

http://www.lydsy.com/JudgeOnline/problem.php?id=1131

题目大意

给定一棵树,找到一个根,使所有点的深度和最大

题解

树形DP
我们先把这棵树处理成以1为根的有根树
维护以每个点为根的子树的节点数 size[]
我们逐层 O(1) 查询
a=fa[b],ans[a]
ab,b1,+1
所以得到递推式 ans[i]=ans[fa[i]]size[i]+nsize[i]

{$m 10000000}
const
    maxn=1000005;
var
    w:array[0..3*maxn,1..2]of longint;
    size,fa:array[0..maxn]of longint;
    ans:array[0..maxn]of int64;
    i,j,k:longint;
    n,m,len,a,b,anss:longint;
procedure init(a,b:longint);
begin
    w[len,1]:=b;
    if w[a,2]=0
    then w[a,2]:=len else w[w[a,1],2]:=len;
    w[a,1]:=len; inc(len);
end;

procedure dfs1(a:longint);
var tt:longint;
begin
    size[a]:=1; tt:=w[a,2];
    while tt<>0 do
        begin
            if w[tt,1]<>fa[a]
            then
                begin
                    fa[w[tt,1]]:=a;
                    dfs1(w[tt,1]);
                    inc(size[a],size[w[tt,1]]);
                    ans[a]:=ans[w[tt,1]]+size[w[tt,1]];
                end;
            tt:=w[tt,2];
        end;
end;

procedure dfs2(a:longint);
var tt:longint;
begin
    tt:=w[a,2];
    if a<>1
    then ans[a]:=ans[fa[a]]+n-size[a]-size[a];
    while tt<>0 do
        begin
            if w[tt,1]<>fa[a]
            then dfs2(w[tt,1]);
            tt:=w[tt,2];
        end;
end;

begin
    readln(n); len:=n+1;
    for i:=1 to n-1 do
        begin
            readln(a,b);
            init(a,b); init(b,a);
        end;
    dfs1(1);
    dfs2(1);
    anss:=0; ans[0]:=-1;
    for i:=1 to n do
      if ans[anss]then anss:=i;
    writeln(anss);
end.

你可能感兴趣的:(动态规划—树形DP)