讨论 / 求本题做法?
slzxrly 2012-11-06 03:32:00
点我顶贴 收藏 删除
是贪心还是树形dp?

有大神能详细讲讲么

#1 linjianyu@2012-10-31 22:10:00
回复 删除
回复 楼主slzxrly 的帖子

同求题解。

窃以为是树形动规。

#2 遗忘de国度@2012-11-03 23:43:00
回复 删除
树形dp

f[i][j]表示以i为根 选择的节点与i的距离中最近的至少为j的子树的 权值和最大值

(注意是至少为j,就是说可以比j大,也就是说f[i][j]包含f[i][j+1]的情况 也就是有f[i][j]>=f[i][j+1])

当j>k/2(取下整) f[i][j]=max(sigma(f[s][j-1]),f[i][j+1]) (s为i儿子)

当k/2(取下整)>=j>0 f[i][j]=max(sigma(f[s][k-j-1])-f[k][k-j-1]+f[k][j-1],f[i][j+1]) (s为i儿子 k为i某一儿子) (因为如果有两个儿子都距i小于k/2 则两儿子之间距离小于k)

当j=0 f[i][j]=max(sigma(f[s][k-1]),f[i][j+1])

上面方程有的地方取上整 取下整有点问题,然后加减1也有可能有问题,稍微想一下,分情况讨论就清楚了

反正转移方程差不多是这样,sigma可以处理一下就是n^2的了

#3 slzxrly@2012-11-05 19:18:00
回复 删除
还是WA了。

思路和ls差不多,但答案老是偏大,麻烦给个程序。

#4 linjianyu@2012-11-06 03:32:00
回复 删除
回复 板凳遗忘de国度 的帖子

感谢神牛。

附代码:

var

i,j,tot,x,y,n,k:longint;

v:array[1..100000] of boolean;

f,tmp,q:array[1..100000,0..102] of longint;

a:array[1..300001,1..2] of longint;

w:array[1..100000] of longint;

procedure dfs(k1:longint);

var

i,j,x,y:longint;

begin

v[k1]:=true;

x:=k1;

while a[x,2]<>0 do

begin

y:=a[a[x,2],1];

if not v[y] then

begin

dfs(y);

for i:=0 to k do tmp[k1,i]:=tmp[k1,i]+f[y,i];

for i:=0 to k-2 do

if f[y,i]-f[y,k-i-2]>q[k1,i] then

q[k1,i]:=f[y,i]-f[y,k-i-2];

end;

x:=a[x,2];

end;

for i:=k downto 0 do

begin

if i>=(k+1) div 2 then

begin

if tmp[k1,i-1]>f[k1,i+1] then

f[k1,i]:=tmp[k1,i-1]

else f[k1,i]:=f[k1,i+1];

end

else if i=0 then

begin

if tmp[k1,k-1]+w[k1]>f[k1,i+1] then

f[k1,i]:=tmp[k1,k-1]+w[k1]

else f[k1,i]:=f[k1,i+1];

end

else if i<(k+1) div 2 then

begin

if tmp[k1,k-i-1]+q[k1,i-1]>f[k1,i+1] then

f[k1,i]:=tmp[k1,k-i-1]+q[k1,i-1]

else f[k1,i]:=f[k1,i+1];

end;

end;

end;

begin

readln(n,k);

inc(k);

for i:=1 to n do

read(w[i]);

tot:=n;

for i:=1 to n-1 do

begin

readln(x,y);

inc(tot); a[tot,1]:=y; a[tot,2]:=a[x,2]; a[x,2]:=tot;

inc(tot); a[tot,1]:=x; a[tot,2]:=a[y,2]; a[y,2]:=tot;

end;

dfs(1);

writeln(f[1,0]);

end.

查看更多回复
提交回复