题目描述
SJY有一天被LLT紧急召去计算一些可能的损失。LLT元首管理的SHB国的交通形成了一棵树,现在将会出现一颗陨石砸在SHB国中,并且陨石砸毁的必定是SHB国构成的交通树上的一条路径。SHB国的损失可表示为被砸毁的路径上的所有城市价值之积。现在还暂时无法确定陨石的掉落路线,所以LLT元首希望SJY能够告诉他SHB国在受到每一种砸毁方式后会受到的损失之和模10086之后的值。注意:单独一个节点也被认为是合法的路径。
输入
第1行一个数n,表示城市数。
第2行n个数,第i个数表示第i个城市的价值。
第3到n+1行,每行两个数u,v,表示城市u,v之间有一条道路。
输出
包含一个数,表示SHB国将受到的损失之和。
样例输入
5
7 6 6 1 1
1 2
2 3
2 4
1 5
样例输出
778
提示
【数据规模和约定】
n<=100;
n<=3000;
n<=100000
题意
给你一棵树,求树上任意一条路径的节点的积的和。
题解
(1)头尾的lca等于头或尾
f[i]=∑f[v[i]]∗a[i],f[i]表示以i节点为头(尾)的路径的乘积之和
(2)头尾的lca不为头或尾,即倒“V”型
我们发现若两点(u,v)的lca为i ,那么可以划分为u到i的直线*v到i的直线。
那么lca为i的路径乘积之和为
对于搜到的每一个子节点,ans:=ans+sum*f[v];sum:=sum+f[v]*a[u];
const oo=10086;maxn=200010; var n,i,u,v,tot,ans:longint; a,vet,next,head,f:array[0..maxn] of longint; procedure add(u,v:longint); begin inc(tot); vet[tot]:=v; next[tot]:=head[u]; head[u]:=tot; inc(tot); vet[tot]:=u; next[tot]:=head[v]; head[v]:=tot; end; procedure dfs(u,pre:longint); var e,v:longint; begin e:=head[u]; while e<>0 do begin v:=vet[e]; if v<>pre then begin dfs(v,u); ans:=(ans+(f[u]-a[u]+oo)*f[v]) mod oo; f[u]:=(f[u]+f[v]*a[u]) mod oo; end; e:=next[e]; end; ans:=(ans+f[u]) mod oo; end; begin read(n); for i:=1 to n do begin read(a[i]); f[i]:=a[i]; end; for i:=1 to n-1 do begin read(u,v); add(u,v); end; dfs(1,0); write(ans); end.
时间: 2024-10-09 21:34:03