您的位置:首页 > 其它

统计损失

2015-11-01 14:42 267 查看

题目

SJY有一天被LLT紧急召去计算一些可能的损失。LLT元首管理的SHB国的交通形成了一棵树,现在将会出现一颗陨石砸在SHB国中,并且陨石砸毁的必定是SHB国构成的交通树上的一条路径。SHB国的损失可表示为被砸毁的路径上的所有城市价值之积。现在还暂时无法确定陨石的掉落路线,所以LLT元首希望SJY能够告诉他SHB国在受到每一种砸毁方式后会受到的损失之和模10086之后的值。注意:单独一个节点也被认为是合法的路径。

题意

给你一棵树,求树上任意一条路径的节点的积的和。

分析

我们很自然的想到了树形dp,那么怎么dp呢?

我们可以先考虑一下它所说的路径是什么?

明显有两种情况:

1.头尾的lca为它们的其中一个

2.头尾的lca不是它们中的一个(即是一个“V”字形的路径)

考虑完了,我们可以设状态:

我们用f[i]f[i]表示经过头(或尾)为i的第一种情况的答案和(直线)。

那么:

f[i]=∑f[son[i]]∗v[i](k=son[i])f[i]=\sum{f[son[i]]*v[i]}(k=son[i])

第二种情况其实并没有那么麻烦,我们发现若两点(x,y)的lca为i

那么可以划分为x到i的直线(第一种情况)*y到i的直线。

且第二种情况是不能传递上fa[i]的(想想为什么)

然后我们便可以直接计算第二种情况,第一种就转移即可。

到此,便很好的解决了这个问题了。

[code]const mo=10086;
var
    n,i,x,y,nu:longint;ans:int64;
    c,f:array[1..100000] of longint;
    b,next,last:array[1..200000] of longint;
procedure insert(x,y:longint);
begin
   inc(nu);
   b[nu]:=y;
   next[nu]:=last[x];
   last[x]:=nu;
end;
procedure dfs(x,y:longint);
var p:longint;su:int64;
begin
    p:=last[x];su:=0;
    while p<>0 do begin
        if b[p]<>y then begin
        dfs(b[p],x);
        f[x]:=(f[x]+f[b[p]]*c[x])mod mo;
        ans:=(ans+su*f[b[p]]*c[x])mod mo;
        su:=su+f[b[p]];end;
        p:=next[p];
    end;
    ans:=(ans+f[x])mod mo;
end;
begin
    readln(n);
    for i:=1 to n do begin read(c[i]);f[i]:=c[i];end;
    for i:=1 to n-1 do begin
       readln(x,y);
       insert(x,y);
       insert(y,x);
    end;
    dfs(1,0);
    writeln(ans);
end.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: