填坑……链接:http://cogs.pro/cogs/problem/problem.php?pid=2478
题意:求出:。
日常题面不符系列……实际上这是个树归……从下向上,对于每个节点,他对于某个点做出的贡献就是子树的大小乘上(子树总大小减去这棵子树大小)再加上该点乘权值,用式子写就是$ans[root]=size[root]*(sum((size[root]-size[belong[v]]))+1)$。
递推即可。
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 const int maxn=1000005; 7 struct node 8 { 9 int from,to,next; 10 }edge[maxn<<1]; 11 int head[maxn],tot; 12 void addedge(int u,int v) 13 { 14 edge[++tot]=(node){u,v,head[u]};head[u]=tot; 15 } 16 int weight[maxn],n,size[maxn]; 17 long long ans=0; 18 void dfs(int root) 19 { 20 size[root]=1; 21 for(int i=head[root];i;i=edge[i].next) 22 { 23 int v=edge[i].to; 24 if(size[v])continue; 25 dfs(v); 26 ans+=1ll*size[v]*1ll*weight[root]*1ll*size[root]; 27 size[root]+=size[v]; 28 } 29 ans+=1ll*weight[root]; 30 } 31 int haha() 32 { 33 freopen("easy_LCA.in","r",stdin); 34 freopen("easy_LCA.out","w",stdout); 35 scanf("%d",&n); 36 for(int i=1;i<=n;i++)scanf("%d",&weight[i]); 37 for(int i=1;i<n;i++) 38 { 39 int x,y;scanf("%d%d",&x,&y); 40 addedge(x,y);addedge(y,x); 41 } 42 dfs(1); 43 printf("%lld\n",ans); 44 } 45 int sb=haha(); 46 int main(){;}